-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[PE-93] refactor: editor mentions extension #6178
base: preview
Are you sure you want to change the base?
Conversation
WalkthroughThe pull request introduces a series of changes primarily focused on enhancing the search and mention functionalities within the editor components. A new Changes
Suggested labels
Suggested reviewers
Poem
Tip CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 12
🧹 Outside diff range and nitpick comments (25)
space/core/components/editor/index.ts (1)
Line range hint
1-6
: Consider adding JSDoc documentation for the exported modules.Since this is a key entry point for editor components, adding documentation about the purpose and contents of each module would improve maintainability.
Add documentation like this:
+/** + * @module editor + * @description Core editor components and utilities + * + * - embeds: Editor mention and embed components + * - lite-text-editor: Lightweight text editor implementation + * - lite-text-read-only-editor: Read-only version of lite editor + * - rich-text-read-only-editor: Read-only rich text editor + * - toolbar: Editor toolbar components + */ export * from "./embeds"; export * from "./lite-text-editor"; export * from "./lite-text-read-only-editor"; export * from "./rich-text-read-only-editor"; export * from "./toolbar";space/core/components/editor/lite-text-read-only-editor.tsx (1)
26-26
: Consider adding explicit typing for EditorMentionsRoot propsTo improve type safety, consider explicitly typing the props passed to
EditorMentionsRoot
.- renderComponent: (props) => <EditorMentionsRoot {...props} />, + renderComponent: (props: EditorMentionsRootProps) => <EditorMentionsRoot {...props} />,space/core/components/editor/rich-text-read-only-editor.tsx (1)
18-32
: Consider adding JSDoc documentationThe component would benefit from JSDoc comments explaining the mention handling behavior and EditorMentionsRoot integration.
+/** + * A read-only rich text editor component that supports mentions. + * @param props - Component props excluding disabledExtensions, fileHandler, and mentionHandler + * @param ref - Reference to access editor API + */ export const RichTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, RichTextReadOnlyEditorWrapperProps>(web/core/hooks/use-editor-mention.tsx (1)
40-62
: UseforEach
Instead ofmap
for Side EffectsIn the loop over
Object.keys(res)
, the returned array frommap
is not utilized. Since the purpose is side effects (i.e., buildingsuggestionSections
), it's more appropriate to useforEach
.Suggested Change:
Replace
map
withforEach
:- Object.keys(res).map((key) => { + Object.keys(res).forEach((key) => {This clarifies the intent and avoids any confusion regarding unused return values.
packages/editor/src/core/extensions/slash-commands/command-menu.tsx (1)
Line range hint
28-74
: Consider Consolidating Keyboard Event HandlingWith the addition of the
onKeyDown
handler viauseImperativeHandle
, there may be redundancy with the existinguseEffect
that adds a keydown listener todocument
. Consolidating these may prevent potential conflicts and simplify the component.Suggestion:
Evaluate if both keyboard event handlers are necessary. If external components handle keyboard events via the ref, you might remove the
useEffect
to avoid duplicate event listeners:- useEffect(() => { - const navigationKeys = ["ArrowUp", "ArrowDown", "Enter"]; - const onKeyDown = (e: KeyboardEvent) => { - // existing key handling logic - }; - document.addEventListener("keydown", onKeyDown); - return () => { - document.removeEventListener("keydown", onKeyDown); - }; - }, [sections, selectedIndex, setSelectedIndex, selectItem]);Ensure that all necessary keyboard interactions are still effectively managed after consolidation.
apiserver/plane/app/views/search/base.py (2)
258-258
: Enforce a maximum limit on thecount
parameterTo prevent potential performance issues or abuse, consider enforcing a maximum limit on the
count
parameter. This ensures that clients cannot request an excessive number of results.Apply this diff to set a maximum limit:
try: count = int(request.query_params.get("count", 5)) + max_count = 100 # Define a sensible maximum limit + if count > max_count: + count = max_count except ValueError: return Response({"error": "Invalid 'count' parameter"}, status=status.HTTP_400_BAD_REQUEST)
263-449
: Refactor to reduce code duplicationThe repetitive patterns in handling different
query_type
cases can be refactored to enhance maintainability and adhere to the DRY (Don't Repeat Yourself) principle. Consider abstracting common logic into helper functions.packages/editor/src/core/types/mention.ts (1)
13-17
: Consider adding JSDoc comments for better documentation.While the types are well-structured, adding JSDoc comments would improve code documentation and IDE support.
+/** Represents a section of mention suggestions */ export type TMentionSection = { key: string; title?: string; items: TMentionSuggestion[]; }; +/** Props passed to the mention component renderer */ export type TMentionComponentProps = Pick<TMentionSuggestion, "entity_identifier" | "entity_name">; +/** Handler for read-only mention functionality */ export type TReadOnlyMentionHandler = { renderComponent: (props: TMentionComponentProps) => React.ReactNode; }; +/** Full mention handler with search capability */ export type TMentionHandler = TReadOnlyMentionHandler & { searchCallback?: (query: string) => Promise<TMentionSection[]>; };Also applies to: 19-19, 21-27
packages/editor/src/core/extensions/mentions/mention-node-view.tsx (1)
19-23
: Consider using more specific CSS class names.The class name 'mention-component' could potentially conflict with other components. Consider using a more specific naming convention.
- <NodeViewWrapper className="mention-component inline w-fit"> + <NodeViewWrapper className="editor-mention-component inline w-fit">space/core/components/editor/embeds/mentions/user.tsx (2)
24-32
: Extract link construction to a helper function.Consider moving the profile link construction to a helper function for better reusability and maintainability.
+const getUserProfileLink = (workspaceSlug: string, userId: string) => + `/${workspaceSlug}/profile/${userId}`; export const EditorUserMention: React.FC<Props> = observer((props) => { // ... - const profileLink = `/${workspaceSlug}/profile/${id}`; + const profileLink = getUserProfileLink(workspaceSlug, id); // ... });
26-28
: Consider extracting styles to a constant or utility function.The conditional class names could be extracted to improve readability and reusability.
+const getMentionStyles = (isCurrentUser: boolean) => cn( + "not-prose inline px-1 py-0.5 rounded bg-yellow-500/20 text-yellow-500 no-underline", + { "bg-custom-primary-100/20 text-custom-primary-100": isCurrentUser } +); export const EditorUserMention: React.FC<Props> = observer((props) => { // ... return ( <div - className={cn("not-prose inline px-1 py-0.5 rounded bg-yellow-500/20 text-yellow-500 no-underline", { - "bg-custom-primary-100/20 text-custom-primary-100": id === currentUser?.id, - })} + className={getMentionStyles(id === currentUser?.id)} >packages/editor/src/core/helpers/tippy.ts (1)
33-55
: Consider extracting navigation logic into separate functionsThe navigation logic for up/down directions contains similar patterns. Consider extracting these into separate functions for better maintainability.
+const moveUp = (section: number, item: number, sections: any[]) => { + item--; + if (item < 0) { + section--; + if (section < 0) section = sections.length - 1; + item = sections[section]?.items?.length - 1; + } + return { section, item }; +}; +const moveDown = (section: number, item: number, sections: any[]) => { + item++; + if (item >= sections[section]?.items?.length) { + section++; + if (section >= sections.length) section = 0; + item = 0; + } + return { section, item }; +}; if (direction === "up") { - // current implementation + const result = moveUp(nextSection, nextItem, sections); + nextSection = result.section; + nextItem = result.item; } else { - // current implementation + const result = moveDown(nextSection, nextItem, sections); + nextSection = result.section; + nextItem = result.item; }web/core/components/editor/rich-text-editor/rich-text-editor.tsx (1)
28-31
: Consider adding loading state handlingThe
useEditorMention
hook might benefit from exposing a loading state to show feedback during mention searches.-const { fetchMentions } = useEditorMention({ +const { fetchMentions, isLoading } = useEditorMention({ projectId: projectId?.toString() ?? "", workspaceSlug: workspaceSlug?.toString() ?? "", });packages/types/src/search.d.ts (1)
11-69
: Consider enhancing type safety with strict null checks.The response types are well-structured, but consider adding explicit null checks for optional fields. This would help prevent potential runtime errors when handling search results.
Example enhancement:
export type TSearchResponse = { - cycle?: TCycleSearchResponse[]; + cycle?: TCycleSearchResponse[] | null; - issue?: TIssueSearchResponse[]; + issue?: TIssueSearchResponse[] | null; // Apply similar changes to other optional arrays };packages/editor/src/core/extensions/mentions/utils.ts (1)
21-43
: Enhance error handling in dropdown initialization.The
onStart
method could benefit from more robust error handling:
- Add error logging for failed initialization
- Handle edge cases when component creation fails
Example enhancement:
onStart: (props: { editor: Editor; clientRect: DOMRect }) => { if (!searchCallback) return; if (!props.clientRect) return; + try { component = new ReactRenderer<CommandListInstance, MentionsListDropdownProps>( // ... existing code ); + } catch (error) { + console.error('Failed to initialize mentions dropdown:', error); + return; + } // ... rest of the code },packages/editor/package.json (1)
40-40
: LGTM! Consider version constraints for better stability.While using "*" is common in monorepos for internal packages, consider using a more specific version range (e.g., "^1.0.0") if the types package starts following semantic versioning.
web/core/components/editor/embeds/mentions/user.tsx (4)
16-18
: Consider extending Props interface for better flexibility.The Props interface could benefit from optional properties for customization, such as
className
for styling overrides.type Props = { id: string; + className?: string; + showTooltip?: boolean; };
23-24
: Consider using a custom hook for popper logic.The popper-related state and configuration could be extracted into a reusable hook for better maintainability.
// usePopper.ts export const useUserMentionPopper = () => { const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null); const [referenceElement, setReferenceElement] = useState<HTMLAnchorElement | null>(null); const popper = usePopper(referenceElement, popperElement, { placement: "bottom-start", modifiers: [{ name: "preventOverflow", options: { padding: 12 } }], }); return { popperElement, setPopperElement, referenceElement, setReferenceElement, ...popper }; };
69-77
: Add loading state for avatar.Consider adding a loading state for the avatar while the image is being fetched.
<Avatar src={getFileURL(userDetails?.avatar_url ?? "")} name={userDetails?.display_name} size={40} className="text-xl" showTooltip={false} + fallback={<div className="animate-pulse bg-custom-background-80 rounded-full size-10" />} />
79-82
: Add title attribute for better UX.Consider adding a title attribute to the link for better user experience when hovering.
<Link href={profileLink} + title={`${userDetails?.first_name} ${userDetails?.last_name}`} className="not-prose font-medium text-custom-text-100 text-base hover:underline" >
web/core/components/editor/lite-text-editor/lite-text-editor.tsx (1)
75-80
: Enhance error handling in searchCallbackWhile the error handling is good, consider providing more specific error information to help with debugging.
searchCallback: async (query) => { const res = await fetchMentions(query); - if (!res) throw new Error("Failed in fetching mentions"); + if (!res) throw new Error(`Failed to fetch mentions for query: ${query}`); return res; },web/core/services/project/project.service.ts (1)
166-185
: Consider improving query_type parameter handling.While the implementation is correct, consider moving the query_type array joining logic to a separate utility function for better maintainability and reusability.
Here's a suggested refactor:
+const formatQueryTypes = (types: TSearchEntities[]): string => types.join(","); + async searchEntity( workspaceSlug: string, projectId: string, params: { query_type: TSearchEntities[]; count?: number; query: string; } ): Promise<TSearchResponse> { return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/search/`, { params: { ...params, - query_type: params.query_type.join(","), + query_type: formatQueryTypes(params.query_type), }, })web/core/components/pages/editor/editor-body.tsx (1)
211-216
: Improve error message in searchCallback.The error message "Failed in fetching mentions" could be more descriptive to aid in debugging.
searchCallback: async (query) => { const res = await fetchMentions(query); - if (!res) throw new Error("Failed in fetching mentions"); + if (!res) throw new Error("Failed to fetch mentions: No response received from the server"); return res; },packages/editor/src/core/hooks/use-editor.ts (2)
33-33
: Consider adding JSDoc comments for better documentation.The type improvements look good! To further enhance maintainability, consider adding JSDoc comments to document the purpose and expected shape of these props:
+/** Additional extensions to be included in the editor */ extensions?: Extensions; +/** Handler for mention functionality including search and suggestions */ mentionHandler: TMentionHandler;Also applies to: 39-39
Line range hint
48-90
: Consider enhancing error handling during editor initialization.While the changes look good, consider adding more robust error handling during editor initialization. This could help catch and handle potential issues with the new mention handler implementation.
const editor = useTiptapEditor({ + onError: (error) => { + console.error('Editor initialization failed:', error); + handleEditorReady?.(false); + }, autofocus, editorProps: { ...CoreEditorProps({
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (71)
apiserver/plane/app/urls/search.py
(2 hunks)apiserver/plane/app/views/__init__.py
(1 hunks)apiserver/plane/app/views/search/base.py
(3 hunks)packages/editor/package.json
(1 hunks)packages/editor/src/core/components/editors/document/read-only-editor.tsx
(2 hunks)packages/editor/src/core/components/editors/editor-wrapper.tsx
(2 hunks)packages/editor/src/core/extensions/core-without-props.ts
(2 hunks)packages/editor/src/core/extensions/extensions.tsx
(3 hunks)packages/editor/src/core/extensions/mentions/extension-config.ts
(1 hunks)packages/editor/src/core/extensions/mentions/extension.tsx
(1 hunks)packages/editor/src/core/extensions/mentions/index.ts
(1 hunks)packages/editor/src/core/extensions/mentions/mention-node-view.tsx
(1 hunks)packages/editor/src/core/extensions/mentions/mentions-list-dropdown.tsx
(1 hunks)packages/editor/src/core/extensions/mentions/mentions-list.tsx
(0 hunks)packages/editor/src/core/extensions/mentions/mentions-without-props.tsx
(0 hunks)packages/editor/src/core/extensions/mentions/types.ts
(1 hunks)packages/editor/src/core/extensions/mentions/utils.ts
(1 hunks)packages/editor/src/core/extensions/read-only-extensions.tsx
(3 hunks)packages/editor/src/core/extensions/slash-commands/command-menu.tsx
(5 hunks)packages/editor/src/core/extensions/slash-commands/root.tsx
(2 hunks)packages/editor/src/core/helpers/tippy.ts
(1 hunks)packages/editor/src/core/hooks/use-editor.ts
(3 hunks)packages/editor/src/core/hooks/use-read-only-editor.ts
(3 hunks)packages/editor/src/core/types/collaboration.ts
(2 hunks)packages/editor/src/core/types/editor.ts
(4 hunks)packages/editor/src/core/types/index.ts
(1 hunks)packages/editor/src/core/types/mention-suggestion.ts
(0 hunks)packages/editor/src/core/types/mention.ts
(1 hunks)packages/types/.prettierrc
(1 hunks)packages/types/src/index.d.ts
(1 hunks)packages/types/src/search.d.ts
(1 hunks)space/ce/components/editor/embeds/index.ts
(1 hunks)space/ce/components/editor/embeds/mentions/index.ts
(1 hunks)space/ce/components/editor/embeds/mentions/root.tsx
(1 hunks)space/ce/components/editor/index.ts
(1 hunks)space/core/components/editor/embeds/index.ts
(1 hunks)space/core/components/editor/embeds/mentions/index.ts
(1 hunks)space/core/components/editor/embeds/mentions/root.tsx
(1 hunks)space/core/components/editor/embeds/mentions/user.tsx
(1 hunks)space/core/components/editor/index.ts
(1 hunks)space/core/components/editor/lite-text-editor.tsx
(2 hunks)space/core/components/editor/lite-text-read-only-editor.tsx
(2 hunks)space/core/components/editor/rich-text-editor.tsx
(2 hunks)space/core/components/editor/rich-text-read-only-editor.tsx
(2 hunks)space/core/store/mentions.store.ts
(0 hunks)space/core/store/root.store.ts
(0 hunks)space/ee/components/editor/index.ts
(1 hunks)web/ce/components/editor/embeds/index.ts
(1 hunks)web/ce/components/editor/embeds/mentions/index.ts
(1 hunks)web/ce/components/editor/embeds/mentions/root.tsx
(1 hunks)web/ce/components/editor/index.ts
(1 hunks)web/ce/constants/editor.ts
(1 hunks)web/ce/hooks/use-additional-editor-mention.tsx
(1 hunks)web/core/components/editor/embeds/index.ts
(1 hunks)web/core/components/editor/embeds/mentions/index.ts
(1 hunks)web/core/components/editor/embeds/mentions/root.tsx
(1 hunks)web/core/components/editor/embeds/mentions/user.tsx
(1 hunks)web/core/components/editor/index.ts
(1 hunks)web/core/components/editor/lite-text-editor/lite-text-editor.tsx
(3 hunks)web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx
(2 hunks)web/core/components/editor/rich-text-editor/rich-text-editor.tsx
(3 hunks)web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx
(2 hunks)web/core/components/pages/editor/editor-body.tsx
(4 hunks)web/core/components/pages/version/editor.tsx
(2 hunks)web/core/hooks/store/index.ts
(0 hunks)web/core/hooks/store/use-mention.ts
(0 hunks)web/core/hooks/use-editor-mention.tsx
(1 hunks)web/core/services/project/project.service.ts
(2 hunks)web/ee/components/editor/index.ts
(1 hunks)web/ee/constants/editor.ts
(1 hunks)web/ee/hooks/use-additional-editor-mention.tsx
(1 hunks)
💤 Files with no reviewable changes (7)
- web/core/hooks/store/index.ts
- space/core/store/root.store.ts
- packages/editor/src/core/types/mention-suggestion.ts
- space/core/store/mentions.store.ts
- packages/editor/src/core/extensions/mentions/mentions-list.tsx
- packages/editor/src/core/extensions/mentions/mentions-without-props.tsx
- web/core/hooks/store/use-mention.ts
✅ Files skipped from review due to trivial changes (21)
- web/core/components/editor/index.ts
- web/core/components/editor/embeds/mentions/index.ts
- space/ce/components/editor/embeds/mentions/index.ts
- web/core/components/editor/embeds/index.ts
- web/ce/components/editor/embeds/index.ts
- space/ce/components/editor/embeds/index.ts
- web/ce/components/editor/index.ts
- space/ce/components/editor/index.ts
- space/core/components/editor/embeds/mentions/index.ts
- web/ee/hooks/use-additional-editor-mention.tsx
- packages/editor/src/core/types/index.ts
- web/ce/components/editor/embeds/mentions/index.ts
- web/ee/components/editor/index.ts
- space/core/components/editor/embeds/index.ts
- web/ee/constants/editor.ts
- space/ce/components/editor/embeds/mentions/root.tsx
- packages/editor/src/core/extensions/mentions/index.ts
- packages/types/.prettierrc
- web/ce/components/editor/embeds/mentions/root.tsx
- packages/editor/src/core/extensions/mentions/types.ts
- space/ee/components/editor/index.ts
🧰 Additional context used
🪛 Biome (1.9.4)
web/ce/hooks/use-additional-editor-mention.tsx
[error] 14-14: Unexpected empty object pattern.
(lint/correctness/noEmptyPattern)
🔇 Additional comments (54)
space/core/components/editor/index.ts (1)
1-1
: LGTM! Let's verify the embeds module.
The addition of the embeds export aligns with the PR's objective to refactor editor mentions.
Let's verify the embeds module and its exports:
✅ Verification successful
Export structure verified and working as expected
The embeds module is properly structured with:
- A clean export chain:
index.ts
->mentions/index.ts
-> components - Two main components:
EditorMentionsRoot
andEditorUserMention
- No naming conflicts with other editor exports
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the embeds module exists and check its exports
# Check if the embeds directory exists
fd --type f "^.*\.(ts|tsx)$" space/core/components/editor/embeds
# Look for exported mention-related components
rg -t ts -t tsx "export.*(?:EditorMentionsRoot|EditorUserMention)" space/core/components/editor/embeds
Length of output: 406
Script:
#!/bin/bash
# Let's check the exports in these files directly
echo "=== Content of embeds/index.ts ==="
cat space/core/components/editor/embeds/index.ts
echo -e "\n=== Content of embeds/mentions/index.ts ==="
cat space/core/components/editor/embeds/mentions/index.ts
echo -e "\n=== Content of embeds/mentions/root.tsx ==="
cat space/core/components/editor/embeds/mentions/root.tsx
echo -e "\n=== Content of embeds/mentions/user.tsx ==="
cat space/core/components/editor/embeds/mentions/user.tsx
# Also check for any potential naming conflicts in other editor exports
echo -e "\n=== Checking for potential naming conflicts ==="
rg -t ts "^export" space/core/components/editor/ --glob '!**/embeds/**'
Length of output: 3506
web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx (2)
2-5
: LGTM! Clean import organization
The import structure properly separates core editor functionality from the mentions feature, aligning with the PR's refactoring objectives.
33-35
: Implementation aligns with refactoring goals
The new mention handler implementation using EditorMentionsRoot
follows a more modular approach, improving code organization.
Let's verify consistent mention handling across different editors:
✅ Verification successful
Let me try a different approach to verify the mention handling implementation.
Mention handling implementation is consistent across editors
The search results confirm that:
- The
EditorMentionsRoot
component is consistently used across all editor variants (lite-text, rich-text) in both read-only and editable modes - The implementation follows the same pattern using
renderComponent: (props) => <EditorMentionsRoot {...props} />
in all instances - The mention handling is properly integrated into both web and space applications
- The types in the editor package properly define the mention handler interface
The new implementation maintains consistency across the codebase and aligns with the modular approach.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for consistent mention handling implementation across editors
# Search for other editor components using EditorMentionsRoot
echo "Checking mention handling implementation across editors..."
rg -l "EditorMentionsRoot" --type typescript
# Verify the mention handler structure
echo "\nVerifying mention handler structure..."
ast-grep --pattern 'mentionHandler = {
renderComponent: $_
}'
Length of output: 363
Script:
#!/bin/bash
# Search for files containing EditorMentionsRoot
echo "Searching for EditorMentionsRoot usage..."
rg "EditorMentionsRoot"
# Search for mentionHandler implementations
echo -e "\nSearching for mentionHandler implementations..."
rg "mentionHandler" -A 2
# Look for editor-related files
echo -e "\nLooking for editor files..."
fd "editor" --type f
Length of output: 19019
web/core/components/pages/version/editor.tsx (2)
6-6
: LGTM! Import changes align with mention handling refactor.
The removal of user-related types and addition of EditorMentionsRoot
aligns with the PR's objective of centralizing mention handling logic.
Also applies to: 9-10
100-100
: Verify read-only mention rendering.
The mention handling has been simplified by delegating to EditorMentionsRoot
. Please ensure that:
- Mentions are properly rendered in read-only mode
- Existing mentions in version history remain intact
✅ Verification successful
EditorMentionsRoot is properly integrated for read-only rendering
The verification shows that:
EditorMentionsRoot
is consistently used across both editable and read-only editors (rich-text-read-only-editor.tsx
,lite-text-read-only-editor.tsx
)- The component handles mentions through a simple entity-based approach that works identically in both read and write modes
- The implementation in
web/core/components/pages/version/editor.tsx
follows the same pattern as other read-only editors in the codebase
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for EditorMentionsRoot usage in read-only contexts
ast-grep --pattern 'DocumentReadOnlyEditorWithRef {
$$$
mentionHandler={{
renderComponent: $_
}}
$$$
}'
# Check if there are any special handling for read-only mentions
rg -A 5 'EditorMentionsRoot.*read.*only'
Length of output: 160
Script:
#!/bin/bash
# Let's try a broader search for EditorMentionsRoot implementation and usage
ast-grep --pattern 'const EditorMentionsRoot = $_'
# Search for any read-only related props or handling in EditorMentionsRoot
rg -A 5 'EditorMentionsRoot.*props'
# Check DocumentReadOnlyEditorWithRef implementation
ast-grep --pattern 'const DocumentReadOnlyEditorWithRef = $_'
# Look for any mention-related props in read-only contexts
rg -A 5 'readOnly.*mention|mention.*readOnly'
Length of output: 8173
space/core/components/editor/lite-text-editor.tsx (2)
5-5
: LGTM: Clean import organization
The addition of EditorMentionsRoot
is properly grouped with related editor components.
48-48
: Verify mention functionality and improve type safety
While the simplified mention handler using component composition is a good approach, please ensure:
- The removal of previous mention logic (hooks, highlights) doesn't break existing functionality
- The props being spread to
EditorMentionsRoot
are properly typed
Let's verify the component implementation and its usage:
Consider adding explicit type information:
- renderComponent: (props) => <EditorMentionsRoot {...props} />,
+ renderComponent: (props: EditorMentionsProps) => <EditorMentionsRoot {...props} />,
✅ Verification successful
Let me gather more information about the types and implementation details.
Based on the results, I can now provide the final response:
Mention functionality is properly typed and implemented
The changes are safe because:
EditorMentionsRoot
is properly typed withTMentionComponentProps
- The component has a clean implementation that handles both user mentions and additional mentions
- The props type is well-defined in the editor package as
Pick<TMentionSuggestion, "entity_identifier" | "entity_name">
The suggestion to add explicit type annotation is unnecessary since the types are already properly inferred from the renderComponent
prop type in TReadOnlyMentionHandler
.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check EditorMentionsRoot implementation and its usage
echo "Checking EditorMentionsRoot implementation:"
ast-grep --pattern 'export const EditorMentionsRoot = $_'
echo "\nChecking other usages of EditorMentionsRoot:"
rg "EditorMentionsRoot" -A 3
echo "\nChecking removed mention-related code:"
git log -S "useMention" --patch
Length of output: 9731
Script:
#!/bin/bash
# Check TMentionComponentProps type definition
echo "Checking TMentionComponentProps type definition:"
rg "type TMentionComponentProps" -A 5
# Check implementation of EditorMentionsRoot
echo "\nChecking EditorMentionsRoot implementation details:"
rg -A 15 "export const EditorMentionsRoot"
# Check for any mention-related hooks that might have been removed
echo "\nChecking for mention hooks:"
rg "useMention" --type ts --type tsx
Length of output: 2615
space/core/components/editor/lite-text-read-only-editor.tsx (2)
4-5
: LGTM: Clean import organization
The addition of EditorMentionsRoot
import is well-organized and aligns with the mention refactoring objectives.
25-27
: Clean implementation of mentionHandler
The new implementation using EditorMentionsRoot
is concise and follows good practices by properly spreading props.
Let's verify consistent usage across other editor components:
✅ Verification successful
EditorMentionsRoot implementation is consistent across editor components
The verification shows that the mentionHandler
implementation using EditorMentionsRoot
is consistently used across all read-only editor components in the codebase:
- space/core/components/editor/lite-text-read-only-editor.tsx
- space/core/components/editor/rich-text-read-only-editor.tsx
- web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx
- web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx
All these components use the same pattern:
mentionHandler={{
renderComponent: (props) => <EditorMentionsRoot {...props} />,
}}
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for consistent EditorMentionsRoot usage across editor components
# Expected: All editor components should use similar mentionHandler implementation
# Search for mentionHandler implementations
rg -A 3 'mentionHandler[=:]' --type typescript
# Search for EditorMentionsRoot usage
ast-grep --pattern 'renderComponent: $_props => <EditorMentionsRoot {...$_props} />'
Length of output: 170
Script:
#!/bin/bash
# Let's try different approaches to find mentionHandler and EditorMentionsRoot usage
# Search for mentionHandler with .tsx extension
rg -A 3 'mentionHandler[=:]' --type tsx
# Search for EditorMentionsRoot imports and usage
rg 'EditorMentionsRoot' --type tsx
# Find all editor-related files to analyze the component usage pattern
fd -e tsx editor
Length of output: 1789
Script:
#!/bin/bash
# Let's try with explicit file extensions and content search
# Search for mentionHandler in all editor files
for file in $(fd -e tsx editor); do
echo "=== $file ==="
grep -A 3 "mentionHandler" "$file" 2>/dev/null
done
# Search for EditorMentionsRoot in all editor files
for file in $(fd -e tsx editor); do
echo "=== $file ==="
grep "EditorMentionsRoot" "$file" 2>/dev/null
done
Length of output: 19306
space/core/components/editor/rich-text-editor.tsx (3)
3-5
: Verify EditorMentionsRoot implementation
The switch from IMentionHighlight to EditorMentionsRoot represents a significant architectural change in how mentions are handled. Let's ensure the new component is properly implemented.
✅ Verification successful
EditorMentionsRoot implementation verified and properly used
The switch from IMentionHighlight to EditorMentionsRoot is a valid architectural change. The component is:
- Properly implemented in
components/editor/embeds/mentions/root.tsx
as a React functional component - Handles mention rendering through a type-switch pattern for different entity types (e.g., user mentions)
- Consistently imported and used across multiple editor components in both web and space packages
- Part of a unified mentions handling approach across different editor variants (rich text, lite text, read-only)
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify EditorMentionsRoot implementation and its usage
# Expected: EditorMentionsRoot should handle mention rendering and interactions
# Check EditorMentionsRoot implementation
ast-grep --pattern 'export const EditorMentionsRoot = $_'
# Check for any existing tests
fd -e test.tsx -e spec.tsx -e test.ts -e spec.ts | grep -i "editormentions"
Length of output: 135
Script:
#!/bin/bash
# Let's try a broader search to locate the EditorMentionsRoot component
# First, search for the file containing EditorMentionsRoot
rg -l "EditorMentionsRoot"
# Then, let's look for any exports containing EditorMentionsRoot
rg "export.*EditorMentionsRoot" -A 5
# Also search for any imports of EditorMentionsRoot to understand its usage
rg "import.*EditorMentionsRoot"
# Check the components directory structure
fd -t f . components/editor/
Length of output: 3277
19-21
:
Breaking Change: mentionHandler interface has been modified
The mentionHandler interface has changed from using highlights
/suggestions
to renderComponent
. This is a breaking change that could affect existing implementations.
20-20
: Verify EditorMentionsRoot props
The component spreads all props directly to EditorMentionsRoot. We should verify the prop types for type safety.
✅ Verification successful
Based on the search results, I can now generate the final response since we have found the type definitions. The TMentionComponentProps
type is defined in the @plane/editor
package and is properly typed with entity_identifier
and entity_name
properties, which are being correctly passed through the spread operator. Here's my final response:
Props are properly typed and safe to spread
The EditorMentionsRoot
component is properly typed with TMentionComponentProps
from @plane/editor
, which includes only the essential props (entity_identifier
and entity_name
). The spread operator usage is safe here as it's passing through a well-defined interface.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check EditorMentionsRoot prop types
# Expected: Props should match what's being passed from mentionHandler
# Find EditorMentionsRoot prop interface
ast-grep --pattern 'interface $_ {
$$$
}' | grep -A 10 "EditorMentions"
Length of output: 73
Script:
#!/bin/bash
# Let's try different approaches to find EditorMentionsRoot component and its type definitions
# Search for EditorMentionsRoot in TypeScript/TSX files
rg "EditorMentionsRoot" -t typescript -t tsx -A 5 -B 5
# Also search for type/interface definitions specifically
rg "type.*EditorMentions|interface.*EditorMentions" -t typescript -t tsx
Length of output: 199
Script:
#!/bin/bash
# Let's try without file type filters since they're not recognized
# First find the file containing EditorMentionsRoot
fd -e tsx -e ts | xargs rg "EditorMentionsRoot" -l
# Then get the content around EditorMentionsRoot usage and definition
rg "EditorMentionsRoot" -A 5 -B 5
Length of output: 24463
Script:
#!/bin/bash
# Let's check the type definition of TMentionComponentProps and related types
rg "type.*TMentionComponentProps|interface.*TMentionComponentProps" -A 5
# Also check for any imports from @plane/editor that might contain the type definitions
rg "from.*@plane/editor.*" -A 1
Length of output: 14794
space/core/components/editor/rich-text-read-only-editor.tsx (2)
4-5
: LGTM: Import aligns with mention refactoring
The addition of EditorMentionsRoot import supports the new component-based approach for handling mentions.
25-27
: Verify EditorMentionsRoot integration
The new mention handling implementation looks good, but let's verify that EditorMentionsRoot receives all necessary props for existing functionality.
✅ Verification successful
Let me gather more information about the MentionComponentProps type to ensure all necessary props are being passed correctly.
Let me check the TMentionSuggestion type since TMentionComponentProps is derived from it.
EditorMentionsRoot integration is properly implemented
The implementation is correct and complete. The verification shows that:
TMentionComponentProps
correctly picks the required props (entity_identifier
andentity_name
) fromTMentionSuggestion
- These props are properly spread to
EditorMentionsRoot
in all editor variants EditorMentionsRoot
correctly destructures and uses these props to render the appropriate mention component
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check EditorMentionsRoot props and usage
# Look for EditorMentionsRoot prop definitions and other usages
# Check component props
ast-grep --pattern 'interface $PROPS {
$$$
}
export const EditorMentionsRoot = ($props: $PROPS)'
# Check other usages for consistency
rg -A 3 'EditorMentionsRoot.*props'
Length of output: 5258
Script:
#!/bin/bash
# Check the TMentionComponentProps type definition
ast-grep --pattern 'type TMentionComponentProps = {
$$$
}'
# Also check for interface definition
ast-grep --pattern 'interface TMentionComponentProps {
$$$
}'
# Look for any imports of TMentionComponentProps
rg 'TMentionComponentProps'
Length of output: 1393
Script:
#!/bin/bash
# Check TMentionSuggestion type definition
ast-grep --pattern 'type TMentionSuggestion = {
$$$
}'
# Also check interface definition
ast-grep --pattern 'interface TMentionSuggestion {
$$$
}'
# Look at the implementation to see how these props are used
rg -A 5 'entity_identifier.*entity_name' 'space/core/components/editor/embeds/mentions/root.tsx'
Length of output: 922
packages/editor/src/core/extensions/mentions/extension.tsx (3)
11-13
: Refactored Extension Enhances Modularity
Renaming to CustomMentionExtension
and restructuring to accept props
improves modularity and configurability of the mentions extension. This enhances the extension's flexibility and reusability.
14-20
: Proper Extension of Parent Options and Inclusion of Render Component
The addOptions
method correctly extends parent options using ...this.parent?.()
and includes the renderComponent
, ensuring that custom rendering capabilities are integrated seamlessly.
26-28
: Suggestion Render Function Configured Appropriately
The suggestion
render function is properly configured using renderMentionsDropdown
with the provided searchCallback
, which should ensure accurate mention suggestions within the editor.
web/core/hooks/use-editor-mention.tsx (1)
23-78
: Efficient Implementation of useEditorMention
Hook
The useEditorMention
hook is well-implemented. The use of useCallback
for fetchMentions
optimizes performance by memoizing the function, and the integration with ProjectService
and useAdditionalEditorMention
effectively manages mention suggestions.
packages/editor/src/core/extensions/slash-commands/command-menu.tsx (1)
91-108
: Efficient Keyboard Event Handling with useImperativeHandle
The use of useImperativeHandle
to expose the onKeyDown
handler is a good approach for managing keyboard interactions from parent components. This enhances the component's reusability and control over keyboard navigation.
packages/editor/src/core/extensions/mentions/mentions-list-dropdown.tsx (1)
1-162
: Well-implemented MentionsListDropdown
component
The component is well-structured and follows React best practices. State management with hooks like useState
, useEffect
, and useCallback
is effectively utilized. The keyboard navigation and item selection logic are clean and efficient.
web/ce/constants/editor.ts (1)
1-4
: Correct addition of EDITOR_MENTION_TYPES
constant
The EDITOR_MENTION_TYPES
constant is properly defined and typed, enhancing clarity and maintainability.
apiserver/plane/app/urls/search.py (1)
18-22
: LGTM! Verify endpoint integration
The new search endpoint URL pattern follows consistent naming and hierarchy conventions.
Let's verify the endpoint integration:
✅ Verification successful
URL pattern properly integrated and endpoint implementation verified
The search endpoint is correctly integrated with:
- Proper view implementation in
apiserver/plane/app/views/search/base.py
- No conflicting URL patterns in the URL configuration
- Consistent URL hierarchy following RESTful conventions
- Complete search functionality for multiple entity types (users, projects, issues, cycles, modules, pages)
- Proper access control checks through project membership
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for any conflicting URL patterns and verify the view is properly imported
rg -A 1 "path\(['\"]workspaces/<str:slug>/projects/<uuid:project_id>/search"
Length of output: 80
Script:
#!/bin/bash
# Let's try a broader search to verify the endpoint integration
# Check for SearchEndpoint view definition and imports
rg -l "class SearchEndpoint"
# Check URL patterns with broader context
rg -B 2 -A 2 "search" apiserver/plane/app/urls/
# Check imports in the search.py file
cat apiserver/plane/app/urls/search.py
Length of output: 2475
Script:
#!/bin/bash
# Let's verify the SearchEndpoint view implementation
cat apiserver/plane/app/views/search/base.py
# Check if there are any other similar search endpoints to ensure no conflicts
rg -l "class.*SearchEndpoint" apiserver/plane/app/views/
Length of output: 15929
space/core/components/editor/embeds/mentions/root.tsx (1)
1-17
:
Consolidate duplicate MentionsRoot implementation
This is an exact duplicate of the implementation in web/core
. To improve maintainability:
- Extract this component to a shared location
- Update imports in both web and space packages
Let's verify all current usages to ensure safe refactoring:
packages/editor/src/core/types/mention.ts (1)
4-11
: LGTM! Well-structured mention suggestion type.
The TMentionSuggestion
type provides a comprehensive structure for mention suggestions with all necessary fields.
packages/editor/src/core/extensions/mentions/mention-node-view.tsx (1)
7-11
: LGTM! Well-typed props definition.
The Props type correctly extends NodeViewProps and properly types the node attributes.
packages/types/src/index.d.ts (1)
31-31
: LGTM! Verify search types usage.
The addition of search types export aligns with the PR objectives for implementing the new search endpoint.
✅ Verification successful
The previous command may have failed because the import path alias "@/types" might not be the actual import path. Let's verify the actual exports and their usage patterns in the codebase.
Export of search types is appropriate and well-defined
The search types are properly defined in packages/types/src/search.d.ts
with comprehensive type definitions for search functionality including:
- Clear entity type definitions (
TSearchEntities
) - Well-structured response types for different entities (users, projects, issues, cycles, modules, pages)
- Proper type inheritance from existing entity interfaces
- Complete search response type (
TSearchResponse
)
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Verify the usage of search types across the codebase
ast-grep --pattern 'import { $_ } from "@/types"' | grep -B 2 -A 2 'search'
Length of output: 75
Script:
#!/bin/bash
# Let's first check what's in the search types file
cat packages/types/src/search.ts
# Also check for any imports using relative paths
rg -g '*.{ts,tsx,js,jsx}' 'from.*["\'].*search["\']' -B 2 -A 2
# And check for potential type usage with ast-grep
ast-grep --pattern 'import { $_ } from "@coderabbit/types"'
Length of output: 212
Script:
#!/bin/bash
# Let's check if the file exists with .d.ts extension since it's a type definition
cat packages/types/src/search.d.ts
# Search for any files containing 'search' in the types directory
fd . packages/types/src --type f
# Look for any imports of search types across the codebase
rg -g '*.{ts,tsx,js,jsx}' -i 'from.*["\'].*/(types|search)["\']'
Length of output: 4759
packages/editor/src/core/types/collaboration.ts (2)
39-39
: Ensure consistent implementation of mention handlers.
The clear separation between TMentionHandler
and TReadOnlyMentionHandler
improves type safety, but requires verification of correct implementation across all editor variants.
Also applies to: 47-47
✅ Verification successful
Consistent implementation of mention handlers verified
The codebase shows a clear and consistent implementation pattern:
TMentionHandler
is correctly used in editable components and hooks (editor.ts, use-editor.ts, extensions.tsx)TReadOnlyMentionHandler
is properly used in read-only variants (read-only-editor.tsx, use-read-only-editor.ts, read-only-extensions.tsx)- The type hierarchy is well-defined with
TMentionHandler
extendingTReadOnlyMentionHandler
with additional search capabilities
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Verify correct handler type usage in editor components
ast-grep --pattern 'class $_ implements $_ {
$$$
mentionHandler: $_
$$$
}'
Length of output: 82
Script:
#!/bin/bash
# Search for mentionHandler type declarations and usages
rg "mentionHandler.*:" -A 2
# Search for TMentionHandler and TReadOnlyMentionHandler definitions and usages
rg "T(ReadOnly)?MentionHandler" -A 2
Length of output: 9506
11-12
: Verify the impact of mention handler type changes.
The shift from highlight/suggestion based types to component-based handler types represents a significant architectural change.
✅ Verification successful
Type changes have been properly implemented across the codebase
Based on the verification results:
- The old types (
IMentionHighlight
andIMentionSuggestion
) have been completely removed with no remaining references. - The new types (
TMentionHandler
andTReadOnlyMentionHandler
) are consistently used across all relevant interfaces and components. - All editor-related components and interfaces have been updated to use the new mention handler types, maintaining type safety.
- The changes follow a clear separation between read-only and editable mention handlers, as evidenced by their usage in respective components.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for any remaining uses of old mention types
rg "IMentionHighlight|IMentionSuggestion" --type ts
# Verify all editor components have been updated to use new types
ast-grep --pattern 'mentionHandler: $_MentionHandler'
Length of output: 109
Script:
#!/bin/bash
# Search for any files importing or using mention-related types
rg "import.*Mention" --type ts -A 3
# Search for mentionHandler property usage in interfaces and types
ast-grep --pattern 'interface $_ {
$$$
mentionHandler$_
$$$
}'
# Search for mentionHandler property usage in component props
ast-grep --pattern 'type $_ = {
$$$
mentionHandler$_
$$$
}'
Length of output: 14446
Script:
#!/bin/bash
# Search for interfaces and types with mentionHandler property
rg "mentionHandler.*:" --type ts -B 2 -A 2
# Search for old type references in type definitions
rg "type.*=.*Mention" --type ts -B 2 -A 2
# Search for any mention-related props in components
ast-grep --pattern 'mentionHandler={$_}'
Length of output: 5090
web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx (2)
34-34
: Confirm consistent mention rendering implementation.
The mentionHandler implementation using renderComponent aligns with the new architecture. However, we should verify this pattern across all editor variants.
✅ Verification successful
The previous pattern might have been too specific. Let's try these alternative approaches to find mention rendering implementations across editor variants.
Mention rendering implementation is consistent across all editor variants
The verification shows that all editor variants consistently use EditorMentionsRoot
component with the same rendering pattern:
- rich-text-editor
- rich-text-read-only-editor
- lite-text-editor
- lite-text-read-only-editor
- version editor
- editor-body
Each implementation follows the same pattern of renderComponent: (props) => <EditorMentionsRoot {...props} />
for the mentionHandler prop.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for consistent mention handler implementation
ast-grep --pattern 'mentionHandler={{
renderComponent: $_
}}'
Length of output: 65
Script:
#!/bin/bash
# Let's try a different pattern to search for mention rendering implementations
ast-grep --pattern 'renderComponent: ($$$) => <EditorMentionsRoot'
# Also search for any EditorMentionsRoot usage
rg "EditorMentionsRoot" -A 2
# And search for mentionHandler prop usage
rg "mentionHandler" -A 2
Length of output: 20458
4-5
: Verify EditorMentionsRoot component implementation.
The addition of EditorMentionsRoot component import supports the new component-based mention rendering approach.
✅ Verification successful
EditorMentionsRoot component implementation is properly structured and functional
The component is correctly implemented as a router for different types of mentions:
- It handles user mentions through
EditorUserMention
component - Falls back to
EditorAdditionalMentionsRoot
for other mention types - Properly accepts and forwards the required
TMentionComponentProps
from the editor
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Verify EditorMentionsRoot component implementation
ast-grep --pattern 'export const EditorMentionsRoot = $_ => {
$$$
}'
Length of output: 72
Script:
#!/bin/bash
# Let's try different approaches to locate EditorMentionsRoot component
# Search for EditorMentionsRoot in all files
rg "EditorMentionsRoot" -A 5
# Find files that might contain the component
fd "editor-mentions-root" --type f
# Look for exports containing EditorMentionsRoot
ast-grep --pattern 'export { $$ EditorMentionsRoot $$ }'
# Check barrel files for re-exports
fd "index.ts" --type f --exec rg "EditorMentionsRoot" {}
Length of output: 14007
Script:
#!/bin/bash
# Let's examine the EditorMentionsRoot component implementation and its dependencies
cat web/core/components/editor/embeds/mentions/root.tsx
# Also check for the user mention component it renders
ast-grep --pattern 'const EditorUserMention = $_ => {
$$$
}'
Length of output: 682
packages/editor/src/core/helpers/tippy.ts (1)
28-28
: Verify the default index behavior
When there are no sections, returning { section: 0, item: 0 }
might lead to undefined behavior since we're trying to access an empty array.
Consider throwing an error or returning undefined
instead:
- if (!sections.length) return { section: 0, item: 0 };
+ if (!sections.length) return undefined;
packages/editor/src/core/components/editors/editor-wrapper.tsx (1)
1-1
: Verify type compatibility with existing extensions
The change from Extension<any, any>[]
to Extensions
type might affect existing extension implementations.
Also applies to: 15-15
✅ Verification successful
Type change from Extension
to Extensions
is safe to use
The change from Extension<any, any>[]
to Extensions
type is a safe refactor as:
Extensions
is the official type from@tiptap/core
used consistently throughout the codebase- The file only changes the type in the Props interface, which is locally scoped
- All extension implementations in the codebase already follow the pattern compatible with the
Extensions
type - The change aligns with the type usage in other editor components and hooks (useEditor, useReadOnlyEditor, etc.)
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for any custom extensions that might be affected by the type change
rg "extends Extension" --type typescript
Length of output: 77
Script:
#!/bin/bash
# Search for any custom extensions or Extension type usage
rg "Extension[<\s]|extends Extension" -t ts -t tsx
# Also search for Extensions type usage to understand the impact
rg "Extensions[<\s]|type.*Extensions" -t ts -t tsx
Length of output: 161
Script:
#!/bin/bash
# Search for Extension and Extensions usage without file type flags
rg "Extension[<\s]|extends Extension"
# Also check for Props interface that uses these types
rg "interface.*Props.*Extension"
Length of output: 5407
Script:
#!/bin/bash
# Let's check the specific file for the type change and its usage
cat packages/editor/src/core/components/editors/editor-wrapper.tsx
# Also check the Extensions type usage in the codebase
rg -B2 -A2 "Extensions(\s|[<>])"
Length of output: 16304
web/core/components/editor/rich-text-editor/rich-text-editor.tsx (1)
52-52
: Verify EditorMentionsRoot props type safety
Ensure that all required props are properly typed and passed to EditorMentionsRoot component.
✅ Verification successful
Props are properly typed and safely passed to EditorMentionsRoot component
The verification shows that:
EditorMentionsRoot
component is properly typed withTMentionComponentProps
from@plane/editor
TMentionComponentProps
is well-defined with required props:entity_identifier
andentity_name
- The component correctly handles these props and renders appropriate components based on the
entity_name
- Props spreading in the parent components is type-safe as it's using the same interface
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for EditorMentionsRoot component definition and its props
rg "EditorMentionsRoot" --type typescript -A 10
Length of output: 82
Script:
#!/bin/bash
# Search for EditorMentionsRoot component definition and its props using ripgrep without file type filter
rg "EditorMentionsRoot" -A 10
Length of output: 23315
Script:
#!/bin/bash
# Search for TMentionComponentProps type definition
rg "TMentionComponentProps" -A 5
# Search for EditorAdditionalMentionsRoot component
rg "EditorAdditionalMentionsRoot" -A 5
Length of output: 5541
packages/types/src/search.d.ts (1)
9-9
: LGTM! Well-defined search entity types.
The TSearchEntities
type clearly defines all searchable entities, aligning with the PR's objectives for mentions functionality.
packages/editor/src/core/extensions/mentions/utils.ts (1)
14-15
: Address TypeScript type issues.
Multiple @ts-expect-error
comments indicate type mismatches with Tiptap and Tippy. Consider:
- Opening issues in respective repositories
- Creating local type declarations to bridge the gaps
Let's check if these issues are already reported:
Also applies to: 32-33
✅ Verification successful
Let me check the specific type issues in the codebase to provide a more accurate assessment.
Let me check the imports and type definitions to better understand the context.
Let me check the specific implementation to understand the type issues better.
Let me check the actual implementation of the suggestion options type to understand the mismatch.
Based on the code analysis, I can now provide a final response:
Type suppression is valid in this case
The @ts-expect-error
comments are addressing known type mismatches between Tiptap's type definitions and their actual implementation:
- The first suppression is for the render function's signature mismatch with Tiptap's
SuggestionOptions["render"]
type - The second suppression is for Tippy.js's incomplete type definitions for its instance methods
These are external dependency type issues that can't be fixed locally. The suppressions are well-documented and necessary until the upstream libraries fix their type definitions.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for related issues in Tiptap and Tippy.js repositories
gh issue list -R ueberdosis/tiptap -S "typescript suggestion types" --json number,title,state
gh issue list -R atomiks/tippyjs -S "typescript types incorrect" --json number,title,state
Length of output: 400
Script:
#!/bin/bash
# Search for ts-expect-error comments and their context
rg "@ts-expect-error" packages/editor/src/core/extensions/mentions/ -B 2 -A 2
# Search for type-related imports from tiptap
rg "from '@tiptap" packages/editor/src/core/extensions/mentions/utils.ts -B 1 -A 1
Length of output: 1130
Script:
#!/bin/bash
# Check imports and type definitions
rg "import.*from.*tiptap" packages/editor/src/core/extensions/mentions/utils.ts
rg "type.*from.*tiptap" packages/editor/src/core/extensions/mentions/utils.ts
# Check the interface/type definitions
ast-grep --pattern 'type $_ = $_'
ast-grep --pattern 'interface $_ $_'
# Check how TMentionHandler is defined
rg "TMentionHandler" packages/editor/src/core/extensions/mentions/ -A 3
Length of output: 65972
Script:
#!/bin/bash
# Check the implementation where ts-expect-error is used
rg -B 5 -A 5 "@ts-expect-error" packages/editor/src/core/extensions/mentions/utils.ts
# Check the related Tiptap types
rg "SuggestionOptions" packages/editor/src/core/extensions/mentions/utils.ts -B 2 -A 2
Length of output: 1444
Script:
#!/bin/bash
# Check the SuggestionOptions type definition
ast-grep --pattern 'interface SuggestionOptions {
$$$
}'
# Check how the render function is used in other places
rg "SuggestionOptions.*render" -A 5
Length of output: 734
packages/editor/src/core/components/editors/document/read-only-editor.tsx (1)
13-13
: LGTM! Clean type transition for mention handler.
The change from the specific mention handler interface to TReadOnlyMentionHandler
improves type consistency across the codebase while maintaining clear component contracts.
Also applies to: 26-26
packages/editor/src/core/extensions/core-without-props.ts (2)
16-16
: LGTM! Import change aligns with mention refactoring.
The switch from CustomMentionWithoutProps
to CustomMentionExtensionConfig
reflects the architectural shift in handling mentions.
Line range hint 100-104
: Verify extension configuration changes.
The removal of function invocation syntax suggests a change in how the mention extension is configured. Please ensure all consumers of this extension are updated accordingly.
✅ Verification successful
No breaking changes in mention extension configuration
The verification shows that CustomMentionWithoutProps
is not used anywhere in the codebase, and the new CustomMentionExtensionConfig
is properly defined in extension-config.ts
and consistently used across the codebase. The change appears to be part of a clean implementation rather than a breaking change, as there are no remnants of old configuration patterns that need updating.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for any remaining usage of old CustomMentionWithoutProps
rg "CustomMentionWithoutProps" --type ts --type tsx
# Search for usage of new CustomMentionExtensionConfig
rg "CustomMentionExtensionConfig" --type ts --type tsx
Length of output: 162
Script:
#!/bin/bash
# Search for any remaining usage of old CustomMentionWithoutProps
rg "CustomMentionWithoutProps"
# Search for usage of new CustomMentionExtensionConfig
rg "CustomMentionExtensionConfig"
# Search for any mention-related configuration patterns
rg -A 3 "mention.*config" -i
Length of output: 3140
packages/editor/src/core/extensions/slash-commands/root.tsx (2)
5-6
: LGTM: Type safety improvement with CommandListInstance
Good move extracting the CommandListInstance type to a separate helper file, improving type organization and reusability.
Line range hint 65-69
: Verify the editor prop usage in ReactRenderer
The ReactRenderer instantiation now includes an additional editor prop. Ensure this prop is properly utilized in the SlashCommandsMenu component.
✅ Verification successful
The editor prop is properly defined and used in the SlashCommandsMenu component
The verification shows that:
- The
SlashCommandsMenuProps
interface explicitly includeseditor: Editor
as a prop - The component is defined with these props and receives them via
forwardRef
- The
ReactRenderer
instantiation correctly passes the editor prop
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check if SlashCommandsMenu uses the editor prop
ast-grep --pattern 'interface SlashCommandsMenuProps {
$$$
editor: $_
$$$
}'
Length of output: 84
Script:
#!/bin/bash
# Let's try to find the SlashCommandsMenu component and its props definition
rg -A 5 "SlashCommandsMenu.*Props" --type typescript
# Also search for the component definition
ast-grep --pattern 'const SlashCommandsMenu = ({ $$$, editor, $$$ }: $_) => {
$$$
}'
# And check the ReactRenderer implementation
rg -A 5 "class ReactRenderer" --type typescript
Length of output: 263
Script:
#!/bin/bash
# Let's try without typescript file type specification
rg -A 5 "SlashCommandsMenu.*Props"
# Search for the component definition
rg -A 5 "const SlashCommandsMenu"
# Check ReactRenderer implementation
rg -A 5 "class ReactRenderer"
Length of output: 3437
web/core/components/editor/lite-text-editor/lite-text-editor.tsx (1)
48-52
: LGTM: Improved mention handling with dedicated hook
Good refactoring to use a dedicated useEditorMention
hook with proper type safety for projectId and workspaceSlug.
packages/editor/src/core/extensions/read-only-extensions.tsx (2)
22-22
: LGTM: Consistent mention handling across extensions
Good improvements:
- Consistent naming with CustomMentionExtension
- Strong typing with TReadOnlyMentionHandler
- Simplified Props interface
Also applies to: 32-32, 39-39
134-134
: Verify mention handler integration
Ensure the CustomMentionExtension properly handles the mentionHandler configuration.
✅ Verification successful
Let me verify the CustomMentionExtensionConfig implementation to ensure it properly supports the mentionHandler properties.
Let me check the type definitions and the mention handler interface.
Let me check the TReadOnlyMentionHandler type to complete the verification.
CustomMentionExtension properly integrates mentionHandler
The implementation correctly handles both required components of TMentionHandler:
- The
renderComponent
prop is properly passed through the extension options and used in MentionNodeView - The
searchCallback
is correctly utilized in the mentions dropdown configuration
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check CustomMentionExtension implementation
ast-grep --pattern 'export const CustomMentionExtension = ($_) => {
$$$
}'
Length of output: 1860
Script:
#!/bin/bash
# Check CustomMentionExtensionConfig implementation
ast-grep --pattern 'export const CustomMentionExtensionConfig = $_'
# Check TMentionHandler type definition
ast-grep --pattern 'type TMentionHandler = {
$$$
}'
Length of output: 4517
Script:
#!/bin/bash
# Search for TMentionHandler interface/type definition
rg "type TMentionHandler" -A 5
# Check renderMentionsDropdown implementation
ast-grep --pattern 'const renderMentionsDropdown = ($_) => {
$$$
}'
Length of output: 357
Script:
#!/bin/bash
# Check TReadOnlyMentionHandler definition
rg "type TReadOnlyMentionHandler" -A 5
# Check renderComponent usage in MentionNodeView
ast-grep --pattern 'const MentionNodeView = ($_) => {
$$$
}'
Length of output: 2052
packages/editor/src/core/hooks/use-read-only-editor.ts (2)
4-4
: Type safety improvements look good!
The changes enhance type safety by:
- Replacing
any
withExtensions
type for better type checking - Using
TReadOnlyMentionHandler
for mentions handling
Also applies to: 19-19, 26-26, 31-31
64-64
: Verify mentionHandler integration
The mentionHandler is now passed directly to CoreReadOnlyEditorExtensions. Let's verify its usage across the codebase.
✅ Verification successful
Let me check how mentionHandler is used within the CoreReadOnlyEditorExtensions to verify its integration.
Let me check the implementation of CustomMentionExtension to verify how it uses the mentionHandler.
Let me check the implementation details of the CustomMentionExtension in the mentions/extension.tsx file.
mentionHandler integration is properly implemented
The verification shows that mentionHandler is correctly integrated:
- It's properly passed from use-read-only-editor to CoreReadOnlyEditorExtensions
- CoreReadOnlyEditorExtensions correctly forwards it to CustomMentionExtension
- CustomMentionExtension properly utilizes the mentionHandler props (searchCallback and renderComponent) in its implementation
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for CoreReadOnlyEditorExtensions usage to verify mentionHandler integration
rg -A 3 "CoreReadOnlyEditorExtensions"
Length of output: 1192
Script:
#!/bin/bash
# Search for mentionHandler usage within CoreReadOnlyEditorExtensions
ast-grep --pattern 'mentionHandler'
Length of output: 243
Script:
#!/bin/bash
# Search for CustomMentionExtension implementation
ast-grep --pattern 'CustomMentionExtension'
Length of output: 551
Script:
#!/bin/bash
# Get the implementation of CustomMentionExtension
cat packages/editor/src/core/extensions/mentions/extension.tsx
Length of output: 866
packages/editor/src/core/extensions/extensions.tsx (2)
21-21
: Good architectural improvements!
The changes improve the codebase by:
- Using consistent naming with
CustomMentionExtension
- Consolidating mention handling into a single handler
- Using proper TypeScript types
Also applies to: 36-36, 44-44
144-144
: Verify mention extension initialization
The mention extension is now initialized with a single handler. Let's verify its implementation.
✅ Verification successful
Let me gather more information about the mention extension configuration and its dependencies.
Let me check one final piece to verify the mention handler type and interface.
Mention extension implementation is properly configured
The mention extension is correctly initialized with the required handler. The implementation shows:
- Proper extension configuration with required attributes and storage
- Correct rendering setup with both node view and dropdown components
- Expected handler interface with searchCallback for mention suggestions
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for CustomMentionExtension implementation
ast-grep --pattern 'export const CustomMentionExtension = ($_) => {
$$$
}'
Length of output: 1860
Script:
#!/bin/bash
# Search for CustomMentionExtensionConfig implementation
ast-grep --pattern 'export const CustomMentionExtensionConfig = $_'
# Search for MentionNodeView implementation
ast-grep --pattern 'export const MentionNodeView = $_'
# Search for renderMentionsDropdown implementation
ast-grep --pattern 'export const renderMentionsDropdown = $_'
Length of output: 11116
Script:
#!/bin/bash
# Search for TMentionHandler type definition
rg "type TMentionHandler" -A 5
Length of output: 285
apiserver/plane/app/views/__init__.py (1)
161-161
: Verify SearchEndpoint implementation
The SearchEndpoint has been added to imports. Let's verify its implementation and usage.
✅ Verification successful
SearchEndpoint is properly implemented and integrated
The SearchEndpoint is correctly implemented in views/search/base.py
and properly integrated into the URL routing at urls/search.py
. It's registered at the endpoint /workspaces/<str:slug>/projects/<uuid:project_id>/search/
and handles project-specific search functionality with query parameters for type and count. The implementation aligns with the codebase's search endpoint hierarchy alongside GlobalSearchEndpoint and IssueSearchEndpoint.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for SearchEndpoint implementation and its URL routing
rg -A 5 "class SearchEndpoint"
# Search for URL patterns using SearchEndpoint
rg "path.*SearchEndpoint.*as_view"
Length of output: 656
Script:
#!/bin/bash
# Let's check the URL patterns in urls.py files that might use SearchEndpoint
fd urls.py | xargs rg "SearchEndpoint"
# Let's also check for any references to SearchEndpoint in the codebase
rg "SearchEndpoint" -B 2 -A 2
# Check if there are any tests for SearchEndpoint
fd test | xargs rg "SearchEndpoint"
Length of output: 2792
packages/editor/src/core/types/editor.ts (2)
1-1
: LGTM! Improved type imports and organization.
The addition of Extensions
from @tiptap/core and the new mention handler types (TMentionHandler
, TReadOnlyMentionHandler
) improves type organization and maintainability.
Also applies to: 14-15
117-117
: Improved type safety for extensions.
The change from any[]
to Extensions
type provides better type safety and IDE support.
Also applies to: 128-128, 131-131
web/core/components/pages/editor/editor-body.tsx (2)
74-78
: LGTM! Clean implementation of editor mentions.
The use of a dedicated hook useEditorMention
improves code organization and reusability.
243-243
: LGTM! Consistent mention handling.
The read-only editor's mentionHandler implementation is consistent with the editable version.
packages/editor/src/core/hooks/use-editor.ts (2)
6-6
: LGTM! Type imports enhance type safety.
The addition of proper type imports (Extensions
and TMentionHandler
) improves type safety by replacing any
types and providing better type definitions for mention handling.
Also applies to: 25-25
91-94
: Verify CoreEditorExtensions integration with new TMentionHandler type.
The change looks correct, but let's verify the integration with CoreEditorExtensions.
✅ Verification successful
Based on the comprehensive search results, I can now provide a final response:
CoreEditorExtensions properly integrates with new TMentionHandler type
The verification confirms proper integration:
- TMentionHandler is correctly defined and used throughout the codebase
- CoreEditorExtensions correctly passes the mentionHandler to CustomMentionExtension
- No legacy mention structure (highlights/suggestions) found in the codebase, except for a console error log
- The type is consistently used across all editor variants (rich text, lite text, read-only)
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify CoreEditorExtensions properly handles TMentionHandler
# Check CoreEditorExtensions implementation
ast-grep --pattern 'function CoreEditorExtensions($_) {
$$$
mentionHandler: $_
$$$
}'
# Check for any direct usage of the old mention structure
rg -l 'highlights.*suggestions' --type ts
Length of output: 137
Script:
#!/bin/bash
# Let's try a different approach to verify the integration
# Find files containing CoreEditorExtensions
rg -l "CoreEditorExtensions" --type ts
# Search for mentionHandler usage in the codebase
rg "mentionHandler" -A 5 -B 5 --type ts
# Look for TMentionHandler type definition and usage
rg "TMentionHandler" -A 3 -B 3 --type ts
# Search for any mention-related types and interfaces
ast-grep --pattern 'interface $_ {
$$$
mention
$$$
}'
Length of output: 57587
Script:
#!/bin/bash
# Let's check the CoreEditorExtensions implementation and CustomMentionExtension usage
# Find CoreEditorExtensions implementation
ast-grep --pattern 'export const CoreEditorExtensions = ($_) => {
$$$
}'
# Check CustomMentionExtension implementation
ast-grep --pattern 'CustomMentionExtension($_)'
# Look for the old mention structure in the codebase
rg "highlights|suggestions" -A 3 -B 3 --type ts
Length of output: 1653
packages/editor/src/core/extensions/mentions/extension-config.ts
Outdated
Show resolved
Hide resolved
packages/editor/src/core/extensions/mentions/extension-config.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (4)
apiserver/plane/app/views/search/base.py (4)
284-299
: Move avatar URL construction to User modelThe avatar URL construction logic should be moved to the User model as a property to maintain DRY principles and ensure consistent URL generation across the application.
Create a property in the User model:
@property def avatar_url(self): if self.avatar_asset: return f"/api/assets/v2/static/{self.avatar_asset}/" return self.avatarThen simplify the query:
- .annotate( - member__avatar_url=Case( - When( - member__avatar_asset__isnull=False, - then=Concat( - Value("/api/assets/v2/static/"), - "member__avatar_asset", - Value("/"), - ), - ), - When( - member__avatar_asset__isnull=True, then="member__avatar" - ), - default=Value(None), - output_field=models.CharField(), - ) - ) + .annotate( + member__avatar_url=F('member__avatar_url') + )
317-318
: Replace magic number with a named constantThe
network=2
condition should use a named constant for better maintainability and clarity.Define the constant at the module level:
+# Project visibility constants +PROJECT_VISIBILITY_PUBLIC = 2 + # ... rest of the code ... - | Q(network=2), + | Q(network=PROJECT_VISIBILITY_PUBLIC),
335-340
: Optimize sequence_id parsing logicThe sequence ID parsing could be optimized by compiling the regex pattern once and handling the parsing more efficiently.
Apply this optimization:
+# Compile regex pattern once at module level +SEQUENCE_ID_PATTERN = re.compile(r"\b\d+\b") + # ... in the method ... - sequences = re.findall(r"\b\d+\b", query) - for sequence_id in sequences: - q |= Q(**{"sequence_id": sequence_id}) + if sequences := SEQUENCE_ID_PATTERN.findall(query): + q |= Q(sequence_id__in=sequences)
275-304
: Extract common query patternsMultiple search implementations share similar patterns for filtering and ordering. Consider extracting these into reusable methods.
Create utility methods:
def _apply_base_filters(self, queryset, slug): return queryset.filter( project__project_projectmember__member=self.request.user, project__project_projectmember__is_active=True, workspace__slug=slug, ) def _apply_search_filter(self, queryset, query, fields): if not query: return queryset q = Q() for field in fields: q |= Q(**{f"{field}__icontains": query}) return queryset.filter(q)This would simplify each search implementation and reduce code duplication.
Also applies to: 342-362, 373-407, 418-435, 446-460
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
apiserver/plane/app/views/search/base.py
(3 hunks)
🔇 Additional comments (2)
apiserver/plane/app/views/search/base.py (2)
5-15
: LGTM: Import statements are well-organized and necessary
The new imports are properly categorized and required for the new search functionality.
Also applies to: 35-36
259-259
:
Add exception handling for count
parameter conversion
The count
parameter is converted to an integer without exception handling, which may raise a ValueError
if an invalid value is provided.
Apply this diff to handle exceptions:
-count = int(request.query_params.get("count", 5))
+try:
+ count = int(request.query_params.get("count", 5))
+except ValueError:
+ return Response({"error": "Invalid 'count' parameter"}, status=status.HTTP_400_BAD_REQUEST)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🔭 Outside diff range comments (2)
web/core/components/issues/description-input.tsx (2)
Line range hint
89-93
: Address the exhaustive-deps warning properlyThe TODO comment acknowledges an ESLint warning about missing dependencies. This should be properly addressed rather than suppressed.
Consider refactoring the debounced save functionality to properly handle all dependencies:
- const debouncedFormSave = useCallback( - debounce(async () => { - handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting("submitted")); - }, 1500), - [handleSubmit, issueId] - ); + const debouncedFormSave = useMemo( + () => + debounce(async () => { + handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting("submitted")); + }, 1500), + [handleSubmit, handleDescriptionFormSubmit, setIsSubmitting] + );
Line range hint
127-137
: Enhance error handling for file uploadsThe current error handling for file uploads only logs the error to console. Consider providing better error feedback to users.
} catch (error) { - console.log("Error in uploading issue asset:", error); - throw new Error("Asset upload failed. Please try again later."); + console.error("Error uploading issue asset:", error); + const errorMessage = error instanceof Error ? error.message : "Asset upload failed"; + throw new Error(`Failed to upload file: ${errorMessage}. Please try again later.`); }
🧹 Nitpick comments (1)
web/core/components/issues/description-input.tsx (1)
Line range hint
36-165
: Consider improving component architectureThe component could benefit from better separation of concerns:
- Extract file upload logic into a custom hook (e.g.,
useFileUpload
)- Consider splitting the form handling into a separate component
- Move the debounced save logic into a custom hook
This would improve maintainability and testability of the code.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
packages/editor/package.json
(1 hunks)packages/types/src/index.d.ts
(1 hunks)web/core/components/editor/rich-text-editor/rich-text-editor.tsx
(3 hunks)web/core/components/issues/description-input.tsx
(1 hunks)web/core/hooks/use-editor-mention.tsx
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- packages/editor/package.json
- packages/types/src/index.d.ts
- web/core/components/editor/rich-text-editor/rich-text-editor.tsx
- web/core/hooks/use-editor-mention.tsx
🔇 Additional comments (2)
web/core/components/issues/description-input.tsx (2)
Line range hint 22-34
: LGTM! Props interface is well-defined
The interface provides a comprehensive set of props for handling issue descriptions, including proper TypeScript types and essential operations.
18-18
: Verify mention functionality after removing useMember hook
The removal of useMember
hook aligns with the PR's objective to refactor the editor mentions extension. However, let's verify that mention functionality is properly handled by the new architecture.
✅ Verification successful
Mention functionality is properly handled by the new architecture
The removal of useMember
hook is safe as the codebase has been refactored to use a centralized mention handling system through EditorMentionsRoot
. This component is consistently integrated across all editor variants:
- Rich text editor
- Lite text editor
- Read-only editors
- Page editors
The EditorMentionsRoot
component (web/core/components/editor/embeds/mentions/root.tsx
) handles user mentions through a dedicated EditorUserMention
component, ensuring consistent mention functionality throughout the application.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that mention handling is properly implemented in the new architecture
# Check if RichTextEditor component is using the new mention handling
ast-grep --pattern 'RichTextEditor {
$$$
mentionHighlights={$_}
$$$
}'
# Check for the new EditorMentionsRoot component usage
rg -A 5 "EditorMentionsRoot"
Length of output: 13935
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (2)
web/core/components/pages/editor/header/options-dropdown.tsx (1)
78-82
: Add error handling for the parsing functionWhile integrating
replaceCustomComponentsFromMarkdownContent
, consider adding error handling to catch any potential exceptions that might occur during the parsing process. This ensures the application remains robust in case of unexpected input or errors.Apply this diff to include error handling:
if (!editorRef) return; const markdownContent = editorRef.getMarkDown(); + let parsedMarkdownContent = ""; + try { parsedMarkdownContent = replaceCustomComponentsFromMarkdownContent({ markdownContent, }); + } catch (error) { + console.error("Error parsing markdown content:", error); + setToast({ + type: TOAST_TYPE.ERROR, + title: "Error!", + message: "Failed to parse markdown content.", + }); + return; + }web/core/components/pages/modals/export-page-modal.tsx (1)
182-182
: Consider improving error loggingUsing
console.error
for error logging is acceptable, but consider implementing a centralized error handling mechanism or using an error tracking service for better monitoring and debugging in production environments.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
packages/editor/src/core/extensions/mentions/extension-config.ts
(1 hunks)web/core/components/pages/editor/header/options-dropdown.tsx
(3 hunks)web/core/components/pages/modals/export-page-modal.tsx
(3 hunks)web/core/hooks/use-parse-editor-content.ts
(1 hunks)web/helpers/editor.helper.ts
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/editor/src/core/extensions/mentions/extension-config.ts
🧰 Additional context used
🪛 Biome (1.9.4)
web/core/hooks/use-parse-editor-content.ts
[error] 167-167: The regular expression includes this negated empty character class.
Negated empty character classes match anything.
If you want to match against [, escape it [.
Otherwise, remove the character class or fill it.
(lint/correctness/noEmptyCharacterClassInRegex)
[error] 180-180: The regular expression includes this negated empty character class.
Negated empty character classes match anything.
If you want to match against [, escape it [.
Otherwise, remove the character class or fill it.
(lint/correctness/noEmptyCharacterClassInRegex)
🔇 Additional comments (4)
web/helpers/editor.helper.ts (1)
Line range hint 1-60
: LGTM!
The refactoring correctly removes the parsing functions, and the remaining code is clean and well-structured.
web/core/components/pages/editor/header/options-dropdown.tsx (2)
28-28
: LGTM!
The import of useParseEditorContent
is correctly added.
64-64
: LGTM!
The hook useParseEditorContent
is properly utilized to enhance the markdown copy functionality.
web/core/components/pages/modals/export-page-modal.tsx (1)
104-106
: LGTM!
The integration of the useParseEditorContent
hook properly replaces direct imports, enhancing modularity and code reuse.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apiserver/plane/app/urls/search.py
(2 hunks)web/core/services/project/project.service.ts
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apiserver/plane/app/urls/search.py
🔇 Additional comments (2)
web/core/services/project/project.service.ts (2)
5-6
: LGTM! Type imports are well-organized.
The new type imports follow the existing pattern and are correctly imported from the shared types package.
175-184
: Verify error handling consistency across the service.
The error handling follows the service pattern, but let's verify it's consistent with other endpoints and handles all error cases properly.
✅ Verification successful
Error handling is consistent with service patterns
The error handling in the entity-search endpoint follows the predominant pattern across the codebase, where most services use throw error?.response?.data
. This is consistent with other endpoints in the project service and aligns with the general error handling approach throughout the application's services.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check error handling consistency across the service
# Check if other methods in the service use the same error handling pattern
rg "throw error\?\.response(\?\.data)?" "web/core/services/project/project.service.ts"
# Look for any error handling variations in similar search endpoints
rg "catch.*error.*throw" "web/core/services/**/*search*.ts"
Length of output: 770
Script:
#!/bin/bash
# Let's check error handling patterns in all service files to get a comprehensive view
rg "\.catch\(\s*\(error\)" "web/core/services/" -A 2
# Also check for any other error handling patterns in the project service
rg "catch.*{" "web/core/services/project/project.service.ts" -A 3
Length of output: 59665
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (2)
web/core/hooks/use-parse-editor-content.ts (1)
189-189
:⚠️ Potential issueFix the regular expressions to avoid using negated empty character classes
The regular expressions include negated empty character classes
[^]*
, which matches any character, potentially leading to unintended matches.Apply these fixes:
-const imageComponentRegex = /<image-component[^>]*src="([^"]+)"[^>]*>[^]*<\/image-component>/g; +const imageComponentRegex = /<image-component[^>]*src="([^"]+)"[^>]*>[\s\S]*?<\/image-component>/g; -const issueEmbedRegex = /<issue-embed-component[^>]*>[^]*<\/issue-embed-component>/g; +const issueEmbedRegex = /<issue-embed-component[^>]*>[\s\S]*?<\/issue-embed-component>/g;Also applies to: 202-202
🧰 Tools
🪛 Biome (1.9.4)
[error] 189-189: The regular expression includes this negated empty character class.
Negated empty character classes match anything.
If you want to match against [, escape it [.
Otherwise, remove the character class or fill it.(lint/correctness/noEmptyCharacterClassInRegex)
web/ce/hooks/use-additional-editor-mention.tsx (1)
25-27
:⚠️ Potential issueRemove empty destructuring and implement the section update logic.
The function currently has an empty destructuring and no implementation, despite receiving typed arguments for response and sections.
const updateAdditionalSections = useCallback((args: TAdditionalEditorMentionHandlerArgs) => { - const {} = args; + const { response, sections } = args; + // TODO: Implement section update logic using response and sections }, []);🧰 Tools
🪛 Biome (1.9.4)
[error] 26-26: Unexpected empty object pattern.
(lint/correctness/noEmptyPattern)
🧹 Nitpick comments (3)
web/core/hooks/use-parse-editor-content.ts (2)
204-205
: Remove or improve performance loggingPerformance logging should not be in production code. Consider using performance monitoring tools instead.
-console.log("Exec time:", end - start); +if (process.env.NODE_ENV === 'development') { + console.debug("Editor content parse time:", end - start, "ms"); +}
167-167
: Improve origin URL handlingThe current origin URL handling could be more robust by providing a fallback.
-const originUrl = typeof window !== "undefined" && (window.location.origin ?? ""); +const originUrl = typeof window !== "undefined" + ? window.location.origin + : process.env.NEXT_PUBLIC_APP_URL ?? "";web/ce/hooks/use-additional-editor-mention.tsx (1)
17-22
: Add JSDoc comments to clarify the return type behavior.The
TAdditionalParseEditorContentReturnType
type allowsundefined
as a return value, but it's not clear under what conditions this occurs. Consider adding documentation to explain the scenarios.+/** + * Return type for parsing editor content + * @returns An object with redirectionPath and textContent when the entity is found + * @returns undefined when the entity is not found or cannot be parsed + */ export type TAdditionalParseEditorContentReturnType = | { redirectionPath: string; textContent: string; } | undefined;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
web/ce/hooks/use-additional-editor-mention.tsx
(1 hunks)web/core/hooks/use-parse-editor-content.ts
(1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
web/ce/hooks/use-additional-editor-mention.tsx
[error] 26-26: Unexpected empty object pattern.
(lint/correctness/noEmptyPattern)
[error] 31-31: Unexpected empty object pattern.
(lint/correctness/noEmptyPattern)
web/core/hooks/use-parse-editor-content.ts
[error] 189-189: The regular expression includes this negated empty character class.
Negated empty character classes match anything.
If you want to match against [, escape it [.
Otherwise, remove the character class or fill it.
(lint/correctness/noEmptyCharacterClassInRegex)
[error] 202-202: The regular expression includes this negated empty character class.
Negated empty character classes match anything.
If you want to match against [, escape it [.
Otherwise, remove the character class or fill it.
(lint/correctness/noEmptyCharacterClassInRegex)
🔇 Additional comments (2)
web/core/hooks/use-parse-editor-content.ts (2)
1-18
: LGTM: Hook setup and dependencies are well-structured
The hook follows React conventions and includes all necessary dependencies for the functionality.
211-215
: LGTM: Clean and well-structured exports
The hook exports are clean and follow React conventions.
const imgElements = doc.querySelectorAll("img"); | ||
await Promise.all( | ||
Array.from(imgElements).map(async (img) => { | ||
// get the image src from the img element | ||
const src = img.getAttribute("src"); | ||
if (src) { | ||
try { | ||
const base64Image = await getBase64Image(src); | ||
img.src = base64Image; | ||
} catch (error) { | ||
// log the error if the image conversion fails | ||
console.error("Failed to convert image to base64:", error); | ||
} | ||
} | ||
}) | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add proper error handling and timeout for image conversion
The current implementation has two potential issues:
- Failed image conversions are only logged to console, which might lead to silent failures in production
- No timeout handling for image conversion, which could cause the function to hang indefinitely
Consider implementing this improvement:
const imgElements = doc.querySelectorAll("img");
-await Promise.all(
- Array.from(imgElements).map(async (img) => {
+const timeout = (ms: number) => new Promise((_, reject) =>
+ setTimeout(() => reject(new Error('Timeout')), ms));
+await Promise.all(
+ Array.from(imgElements).map(async (img) => {
const src = img.getAttribute("src");
if (src) {
try {
- const base64Image = await getBase64Image(src);
+ const base64Image = await Promise.race([
+ getBase64Image(src),
+ timeout(5000) // 5 second timeout
+ ]);
img.src = base64Image;
} catch (error) {
- console.error("Failed to convert image to base64:", error);
+ // Remove the image if conversion fails
+ img.remove();
+ // Log error with context for monitoring
+ console.error("Image conversion failed:", {
+ error,
+ src: src.substring(0, 100), // truncate for logging
+ timestamp: new Date().toISOString()
+ });
}
}
})
);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const imgElements = doc.querySelectorAll("img"); | |
await Promise.all( | |
Array.from(imgElements).map(async (img) => { | |
// get the image src from the img element | |
const src = img.getAttribute("src"); | |
if (src) { | |
try { | |
const base64Image = await getBase64Image(src); | |
img.src = base64Image; | |
} catch (error) { | |
// log the error if the image conversion fails | |
console.error("Failed to convert image to base64:", error); | |
} | |
} | |
}) | |
); | |
const imgElements = doc.querySelectorAll("img"); | |
const timeout = (ms: number) => new Promise((_, reject) => | |
setTimeout(() => reject(new Error('Timeout')), ms)); | |
await Promise.all( | |
Array.from(imgElements).map(async (img) => { | |
// get the image src from the img element | |
const src = img.getAttribute("src"); | |
if (src) { | |
try { | |
const base64Image = await Promise.race([ | |
getBase64Image(src), | |
timeout(5000) // 5 second timeout | |
]); | |
img.src = base64Image; | |
} catch (error) { | |
// Remove the image if conversion fails | |
img.remove(); | |
// Log error with context for monitoring | |
console.error("Image conversion failed:", { | |
error, | |
src: src.substring(0, 100), // truncate for logging | |
timestamp: new Date().toISOString() | |
}); | |
} | |
} | |
}) | |
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
space/core/components/editor/embeds/mentions/user.tsx (1)
32-41
: Enhance render logic with a11y improvements and remove redundant optional chaining.
- The optional chaining on
userDetails
is redundant since we already check for its existence in the earlier condition.- Add ARIA attributes to improve accessibility for screen readers.
return ( <div className={cn("not-prose inline px-1 py-0.5 rounded bg-yellow-500/20 text-yellow-500 no-underline", { "bg-custom-primary-100/20 text-custom-primary-100": id === currentUser?.id, })} + role="button" + aria-label={`Mention ${userDetails.member__display_name}`} > - <Link href={profileLink}>@{userDetails?.member__display_name}</Link> + <Link href={profileLink}>@{userDetails.member__display_name}</Link> </div> );
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
space/core/components/editor/embeds/mentions/user.tsx
(1 hunks)web/core/components/editor/embeds/mentions/user.tsx
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- web/core/components/editor/embeds/mentions/user.tsx
🔇 Additional comments (2)
space/core/components/editor/embeds/mentions/user.tsx (2)
1-11
: LGTM! Well-organized imports and clean type definition.
The imports are properly organized with clear grouping comments, and the Props type is concise and well-defined.
21-30
: LGTM! Proper error handling implemented.
The component correctly handles the case of missing user details by showing a fallback UI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (9)
packages/editor/src/core/extensions/mentions/utils.ts (3)
12-19
: Consider improving type safety for the popup variable.While the component is well-typed, the popup variable uses
any
. Consider creating a proper type for the Tippy instance to improve type safety.- let popup: any | null = null; + let popup: ReturnType<typeof tippy> | null = null;
50-65
: Improve return value documentation for keyboard handling.The keyboard event handler's return values could be more explicit about their meaning:
true
: event was handledfalse
: event should be processed by other handlersAdd JSDoc comments to clarify the return values:
+ /** + * Handles keyboard events for the mentions dropdown + * @returns true if the event was handled, false otherwise + */ onKeyDown: (props: { event: KeyboardEvent }) => {
12-72
: Well-structured implementation aligning with refactoring goals.The implementation successfully separates concerns by:
- Accepting the search callback as a prop instead of handling it internally
- Providing a clean interface for the web application
- Maintaining a clear separation between rendering and data fetching
Consider adding error boundaries around the ReactRenderer to handle potential rendering errors gracefully.
packages/types/src/search.d.ts (3)
68-75
: Improve type safety of TSearchResponseConsider making the response type more strictly typed by using TSearchEntities as keys.
-export type TSearchResponse = { - cycle_mention?: TCycleSearchResponse[]; - issue_mention?: TIssueSearchResponse[]; - module_mention?: TModuleSearchResponse[]; - page_mention?: TPageSearchResponse[]; - project_mention?: TProjectSearchResponse[]; - user_mention?: TUserSearchResponse[]; -}; +export type TSearchResponse = { + [K in TSearchEntities]?: { + 'user_mention': TUserSearchResponse; + 'issue_mention': TIssueSearchResponse; + 'project_mention': TProjectSearchResponse; + 'cycle_mention': TCycleSearchResponse; + 'module_mention': TModuleSearchResponse; + 'page_mention': TPageSearchResponse; + }[K][]; +};
47-47
: Add strict typing for status fieldsThe status fields in TCycleSearchResponse and TModuleSearchResponse could benefit from more specific typing.
- status: ICycle["status"]; + status: "draft" | "started" | "completed" | "cancelled"; - status: IModule["status"]; + status: "planned" | "in-progress" | "completed" | "cancelled";Also applies to: 56-56
9-15
: Add JSDoc comments for better documentationConsider adding JSDoc comments to describe the purpose and usage of each search entity type.
+/** + * Represents the different types of entities that can be mentioned in the editor. + * Used for filtering search results and determining the type of mention being created. + */ export type TSearchEntities = | "user_mention" | "issue_mention" | "project_mention" | "cycle_mention" | "module_mention" | "page_mention";web/core/components/editor/lite-text-editor/lite-text-editor.tsx (1)
91-91
: Consider memoizing the EditorMentionsRoot render functionThe renderComponent function could benefit from memoization to prevent unnecessary re-renders.
+const renderMentionsRoot = React.useCallback((props) => <EditorMentionsRoot {...props} />, []); mentionHandler={{ searchCallback: async (query) => { const res = await fetchMentions(query); if (!res) throw new Error("Failed in fetching mentions"); return res; }, - renderComponent: (props) => <EditorMentionsRoot {...props} />, + renderComponent: renderMentionsRoot, }}Also applies to: 92-92
web/core/components/pages/editor/editor-body.tsx (1)
212-217
: Add error message localization.The error message should be localized for better user experience.
searchCallback: async (query) => { const res = await fetchMentions(query); if (!res) throw new Error("Failed in fetching mentions"); return res; },apiserver/plane/app/views/search/base.py (1)
254-469
: Consider implementing caching and pagination.The search endpoint could benefit from:
- Caching frequently accessed data to improve performance
- Implementing proper pagination for large result sets
Consider implementing Redis caching for search results and using Django's pagination:
from django.core.cache import cache from django.core.paginator import Paginator # Add cache key generation def get_cache_key(self, query_type, query, project_id): return f"search:{query_type}:{project_id}:{query}" # Add cache wrapper def get_cached_results(self, cache_key, queryset, count): cached_data = cache.get(cache_key) if cached_data is not None: return cached_data results = list(queryset[:count]) cache.set(cache_key, results, timeout=300) # Cache for 5 minutes return results
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
apiserver/plane/app/views/search/base.py
(3 hunks)packages/editor/src/core/extensions/mentions/utils.ts
(1 hunks)packages/types/src/search.d.ts
(1 hunks)web/core/components/editor/lite-text-editor/lite-text-editor.tsx
(3 hunks)web/core/components/editor/rich-text-editor/rich-text-editor.tsx
(2 hunks)web/core/components/pages/editor/editor-body.tsx
(5 hunks)web/core/hooks/use-editor-mention.tsx
(1 hunks)web/core/services/project/project.service.ts
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- web/core/hooks/use-editor-mention.tsx
🔇 Additional comments (14)
packages/editor/src/core/extensions/mentions/utils.ts (3)
1-11
: LGTM! Well-organized imports.
The imports are properly organized and grouped with clear comments.
35-36
: Fragile DOM query for editor container.
The current DOM query using querySelector
is fragile.
66-70
: LGTM! Proper cleanup in onExit.
The cleanup logic properly handles both the popup and component instances, and updates the editor state.
web/core/components/editor/rich-text-editor/rich-text-editor.tsx (2)
50-54
: Improve error handling in search callback
The current error handling could be more informative and might swallow useful error details.
31-34
: Verify searchEntity implementation across workspace contexts
The searchEntity implementation assumes both workspaceSlug and projectId are available. Consider handling cases where projectId is undefined.
web/core/components/editor/lite-text-editor/lite-text-editor.tsx (2)
86-91
: Improve error handling in search callback
The error handling pattern is repeated here and could be more informative.
55-59
: LGTM: Consistent mention handling implementation
The implementation of useEditorMention and searchEntity is consistent with the rich-text-editor component, which helps maintain code consistency across different editor variants.
web/core/services/project/project.service.ts (2)
1-7
: LGTM!
The import statements are correctly updated to include the new types required for the search functionality.
174-189
: 🛠️ Refactor suggestion
Add input validation and error handling.
The method should validate required parameters and handle potential errors more gracefully.
Apply this diff to improve the implementation:
async searchEntity(
workspaceSlug: string,
projectId: string,
params: TSearchEntityRequestPayload
): Promise<TSearchResponse> {
+ if (!workspaceSlug || !projectId || !params?.query_type?.length) {
+ throw new Error("Missing required parameters");
+ }
+
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/entity-search/`, {
params: {
...params,
query_type: params.query_type.join(","),
},
})
.then((response) => response?.data)
.catch((error) => {
- throw error?.response?.data;
+ throw error?.response?.data || new Error("Failed to search entities");
});
}
Likely invalid or redundant comment.
web/core/components/pages/editor/editor-body.tsx (3)
19-19
: LGTM!
The imports are correctly updated to support the new mention handling mechanism.
Also applies to: 26-27, 37-37, 42-42
75-79
: LGTM!
The useEditorMention hook is properly configured with the searchEntity callback.
244-244
: LGTM!
The read-only editor's mentionHandler is correctly configured with the EditorMentionsRoot component.
apiserver/plane/app/views/search/base.py (2)
5-19
: LGTM!
The imports are correctly updated to include necessary Django model utilities.
257-259
: Previous review comments still apply.
The validation for query_types and exception handling for the count parameter should be addressed as mentioned in previous review comments.
onStart: (props: { editor: Editor; clientRect: DOMRect }) => { | ||
if (!searchCallback) return; | ||
if (!props.clientRect) return; | ||
component = new ReactRenderer<CommandListInstance, MentionsListDropdownProps>(MentionsListDropdown, { | ||
props: { | ||
...props, | ||
searchCallback, | ||
}, | ||
editor: props.editor, | ||
}); | ||
props.editor.storage.mentionsOpen = true; | ||
// @ts-expect-error - Tippy types are incorrect | ||
popup = tippy("body", { | ||
getReferenceClientRect: props.clientRect, | ||
appendTo: () => | ||
document.querySelector(".active-editor") ?? document.querySelector('[id^="editor-container"]'), | ||
content: component.element, | ||
showOnCreate: true, | ||
interactive: true, | ||
trigger: "manual", | ||
placement: "bottom-start", | ||
}); | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add cleanup in early return cases.
When searchCallback
or clientRect
is not provided, the function returns early without cleaning up any existing instances.
onStart: (props: { editor: Editor; clientRect: DOMRect }) => {
- if (!searchCallback) return;
- if (!props.clientRect) return;
+ if (!searchCallback || !props.clientRect) {
+ popup?.[0]?.destroy();
+ component?.destroy();
+ return;
+ }
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
onStart: (props: { editor: Editor; clientRect: DOMRect }) => { | |
if (!searchCallback) return; | |
if (!props.clientRect) return; | |
component = new ReactRenderer<CommandListInstance, MentionsListDropdownProps>(MentionsListDropdown, { | |
props: { | |
...props, | |
searchCallback, | |
}, | |
editor: props.editor, | |
}); | |
props.editor.storage.mentionsOpen = true; | |
// @ts-expect-error - Tippy types are incorrect | |
popup = tippy("body", { | |
getReferenceClientRect: props.clientRect, | |
appendTo: () => | |
document.querySelector(".active-editor") ?? document.querySelector('[id^="editor-container"]'), | |
content: component.element, | |
showOnCreate: true, | |
interactive: true, | |
trigger: "manual", | |
placement: "bottom-start", | |
}); | |
}, | |
onStart: (props: { editor: Editor; clientRect: DOMRect }) => { | |
if (!searchCallback || !props.clientRect) { | |
popup?.[0]?.destroy(); | |
component?.destroy(); | |
return; | |
} | |
component = new ReactRenderer<CommandListInstance, MentionsListDropdownProps>(MentionsListDropdown, { | |
props: { | |
...props, | |
searchCallback, | |
}, | |
editor: props.editor, | |
}); | |
props.editor.storage.mentionsOpen = true; | |
// @ts-expect-error - Tippy types are incorrect | |
popup = tippy("body", { | |
getReferenceClientRect: props.clientRect, | |
appendTo: () => | |
document.querySelector(".active-editor") ?? document.querySelector('[id^="editor-container"]'), | |
content: component.element, | |
showOnCreate: true, | |
interactive: true, | |
trigger: "manual", | |
placement: "bottom-start", | |
}); | |
}, |
Description
Frontend-
This PR refactors the editor mentions extension. The search callback function and the render component are now passed by the web app instead of handling all the logic inside the editor itself.
It also refactors the logic for arrow key navigation for the mentions component and slash commands menu by extracting the common logic into a separate file.
Backend-
Added a new search endpoint which returns an object with the requested entities based on the search query
Type of Change
Test Scenarios
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Chores