Skip to content

Conversation

@aaryan610
Copy link
Member

@aaryan610 aaryan610 commented Jan 15, 2026

Description

This PR refactors the description input component to pass description_json as a part of the onSubmit callback function.

Type of Change

  • Code refactoring

Summary by CodeRabbit

  • New Features

    • Description input now supports both HTML and structured JSON content for richer editor data.
  • Refactor

    • Unified description submission flow across multiple components to send the combined HTML+JSON payload and streamline save behavior.

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI review requested due to automatic review settings January 15, 2026 10:26
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 15, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

DescriptionInput's public API changes from a string parameter to an object containing description_html and optional description_json; the component also accepts issueSequenceId. Consumers were updated to extract description_html from the new object when calling update operations.

Changes

Cohort / File(s) Summary
Core Component API Refactor
apps/web/core/components/editor/rich-text/description-input/root.tsx
onSubmit now accepts { description_html: string; description_json: object | undefined }. TFormData gains optional description_json. Props adds optional issueSequenceId. RichTextEditor onChange and internal state now handle description_json alongside description_html. Submission sends combined object.
Consumers: update callsites
apps/web/core/components/inbox/content/issue-root.tsx, apps/web/core/components/issues/issue-detail/main-content.tsx, apps/web/core/components/issues/peek-overview/issue-detail.tsx
Each onSubmit handler updated to pass description_html: value.description_html (extracting from the new object) to issueOperations.update instead of passing value directly.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I nibble through code, neat and spry,
HTML and JSON now hop nearby.
Two fields, one basket, tidy and bright—
Description lands soft, just right. ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: refactoring the description input component to handle description_json in the onSubmit callback.
Description check ✅ Passed The PR description covers the main objective (passing description_json in onSubmit) and correctly marks the change type as Code refactoring, but lacks test scenarios, screenshots, and references sections.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

🧹 Recent nitpick comments
apps/web/core/components/editor/rich-text/description-input/root.tsx (1)

256-272: Inconsistent error handling.

Line 257 uses console.log while other error handlers in this file (lines 176, 193) use console.error. Additionally, the catch block at line 270 silently discards the error, making debugging difficult.

♻️ Suggested improvement
            } catch (error) {
-             console.log("Error in uploading asset:", error);
+             console.error("Error in uploading asset:", error);
              throw new Error("Asset upload failed. Please try again later.");
            }
          }}
          duplicateFile={async (assetId: string) => {
            try {
              const { asset_id } = await duplicateEditorAsset({
                assetId,
                entityType: fileAssetType,
                projectId,
                workspaceSlug,
              });
              return asset_id;
-           } catch {
+           } catch (error) {
+             console.error("Error in duplicating asset:", error);
              throw new Error("Asset duplication failed. Please try again later.");
            }
          }}

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a95e008 and 0c37595.

📒 Files selected for processing (1)
  • apps/web/core/components/editor/rich-text/description-input/root.tsx
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,mts,cts}

📄 CodeRabbit inference engine (.github/instructions/typescript.instructions.md)

**/*.{ts,tsx,mts,cts}: Use const type parameters for more precise literal inference in TypeScript 5.0+
Use the satisfies operator to validate types without widening them
Leverage inferred type predicates to reduce the need for explicit is return types in filter/check functions
Use NoInfer<T> utility to block inference for specific type arguments when they should be determined by other arguments
Utilize narrowing in switch(true) blocks for control flow analysis (TypeScript 5.3+)
Rely on narrowing from direct boolean comparisons for type guards
Trust preserved narrowing in closures when variables aren't modified after the check (TypeScript 5.4+)
Use constant indices to narrow object/array properties (TypeScript 5.5+)
Use standard ECMAScript decorators (Stage 3) instead of legacy experimentalDecorators
Use using declarations for explicit resource management with Disposable pattern instead of manual cleanup (TypeScript 5.2+)
Use with { type: "json" } for import attributes; avoid deprecated assert syntax (TypeScript 5.3/5.8+)
Use import type explicitly when importing types to ensure they are erased during compilation, respecting verbatimModuleSyntax flag
Use .ts, .mts, .cts extensions in import type statements (TypeScript 5.2+)
Use import type { Type } from "mod" with { "resolution-mode": "import" } for specific module resolution contexts (TypeScript 5.3+)
Use new iterator methods (map, filter, etc.) if targeting modern environments (TypeScript 5.6+)
Utilize new Set methods like union, intersection, etc., when available (TypeScript 5.5+)
Use Object.groupBy / Map.groupBy standard methods for grouping instead of external libraries (TypeScript 5.4+)
Use Promise.withResolvers() for creating promises with exposed resolve/reject functions (TypeScript 5.7+)
Use copying array methods (toSorted, toSpliced, with) for immutable array operations (TypeScript 5.2+)
Avoid accessing instance fields via super in classes (TypeScript 5....

Files:

  • apps/web/core/components/editor/rich-text/description-input/root.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Enable TypeScript strict mode and ensure all files are fully typed

Files:

  • apps/web/core/components/editor/rich-text/description-input/root.tsx
**/*.{js,jsx,ts,tsx,json,css}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier with Tailwind plugin for code formatting, run pnpm fix:format

Files:

  • apps/web/core/components/editor/rich-text/description-input/root.tsx
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,jsx,ts,tsx}: Use ESLint with shared config across packages, adhering to max warnings limits per package
Use camelCase for variable and function names, PascalCase for components and types
Use try-catch with proper error types and log errors appropriately

Files:

  • apps/web/core/components/editor/rich-text/description-input/root.tsx
🧠 Learnings (1)
📚 Learning: 2025-10-10T13:25:14.810Z
Learnt from: gakshita
Repo: makeplane/plane PR: 7949
File: apps/web/core/components/issues/issue-modal/form.tsx:183-189
Timestamp: 2025-10-10T13:25:14.810Z
Learning: In `apps/web/core/components/issues/issue-modal/form.tsx`, the form reset effect uses a `dataResetProperties` dependency array prop (default: []) to give parent components explicit control over when the form resets. Do not suggest adding the `data` prop itself to the dependency array, as this would cause unwanted resets on every render when the data object reference changes, disrupting user input. The current pattern is intentional and allows the parent to trigger resets only when specific conditions are met.

Applied to files:

  • apps/web/core/components/editor/rich-text/description-input/root.tsx
🧬 Code graph analysis (1)
apps/web/core/components/editor/rich-text/description-input/root.tsx (3)
apps/web/core/components/editor/rich-text/description-input/loader.tsx (1)
  • DescriptionInputLoader (9-33)
apps/web/core/components/editor/rich-text/editor.tsx (1)
  • RichTextEditor (36-98)
packages/utils/src/work-item/base.ts (1)
  • getDescriptionPlaceholderI18n (213-217)
🔇 Additional comments (6)
apps/web/core/components/editor/rich-text/description-input/root.tsx (6)

22-27: LGTM!

The TFormData type extension with description_json?: object aligns with the refactored submission flow. The loose object type is acceptable given JSON structures can vary by editor content.


61-67: LGTM!

The updated onSubmit signature that accepts an object with description_html and description_json is a clean API improvement. This change aligns with the PR objective to pass description_json as part of the callback, and the AI summary confirms consumers have been updated accordingly.


107-107: Issue from previous review addressed.

The issueSequenceId prop is now correctly destructured and passed to the RichTextEditor component at line 219, resolving the previously flagged concern.


140-151: LGTM!

The handler correctly constructs the new payload object with both description_html and description_json, matching the updated onSubmit signature.


208-208: LGTM!

The loader condition correctly shows a loading state until the description is properly initialized. The brief loader display before the useEffect normalizes empty values to "<p></p>" is acceptable behavior.


227-234: LGTM!

The onChange handler correctly processes the editor's output:

  • Updates description_html via the Controller's onChange
  • Syncs description_json and isMigrationUpdate to the form state
  • Marks unsaved changes and triggers the debounced save

This properly captures the refactored data flow where description_json is now part of the submission payload.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@makeplane
Copy link

makeplane bot commented Jan 15, 2026

Linked to Plane Work Item(s)

This comment was auto-generated by Plane

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors the DescriptionInput component to pass both description_html and description_json in the onSubmit callback, preparing the codebase for future use of JSON descriptions alongside HTML descriptions.

Changes:

  • Modified the DescriptionInput component's onSubmit signature to accept an object containing both description_html and description_json
  • Updated the component to capture and pass description_json from the editor's onChange callback
  • Updated all three consumer components to extract description_html from the new object structure

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
apps/web/core/components/editor/rich-text/description-input/root.tsx Refactored component to capture and pass description_json along with description_html in the onSubmit callback
apps/web/core/components/issues/peek-overview/issue-detail.tsx Updated to extract description_html from the new value object structure
apps/web/core/components/issues/issue-detail/main-content.tsx Updated to extract description_html from the new value object structure
apps/web/core/components/inbox/content/issue-root.tsx Updated to extract description_html from the new value object structure

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/core/components/editor/rich-text/description-input/root.tsx (1)

154-168: Reset effect does not clear description_json.

When the form resets (e.g., on entityId or initialValue change), description_json is not reset in either the form state or localDescription. This could cause stale JSON data to persist across entity switches.

Suggested fix
 useEffect(() => {
   if (!entityId) return;
   reset({
     id: entityId,
     description_html: initialValue?.trim() === "" ? "<p></p>" : (initialValue ?? "<p></p>"),
+    description_json: undefined,
     isMigrationUpdate: false,
   });
   setLocalDescription({
     id: entityId,
     description_html: initialValue?.trim() === "" ? "<p></p>" : (initialValue ?? "<p></p>"),
+    description_json: undefined,
     isMigrationUpdate: false,
   });
   // Reset unsaved changes flag when form is reset
   hasUnsavedChanges.current = false;
 }, [entityId, initialValue, reset]);
🤖 Fix all issues with AI agents
In `@apps/web/core/components/editor/rich-text/description-input/root.tsx`:
- Line 107: The prop issueSequenceId is destructured but not forwarded to the
RichTextEditor instance; update the RichTextEditor invocation in this component
to include issueSequenceId (e.g., pass issueSequenceId={issueSequenceId}) so the
editor receives the prop accepted by the RichTextEditor in editor.tsx.
🧹 Nitpick comments (2)
apps/web/core/components/editor/rich-text/description-input/root.tsx (1)

116-120: description_json not initialized in local state.

The localDescription state is missing the description_json field, which could lead to stale or undefined values if accessed before the first onChange event. Consider initializing it for consistency with TFormData.

Suggested fix
 const [localDescription, setLocalDescription] = useState<TFormData>({
   id: entityId,
   description_html: initialValue?.trim() ?? "",
+  description_json: undefined,
   isMigrationUpdate: false,
 });
apps/web/core/components/issues/peek-overview/issue-detail.tsx (1)

87-92: Pre-existing bug: Condition is always true.

The condition on line 88 uses || (OR) instead of && (AND), making it always evaluate to true. Any value satisfies "not undefined OR not null". This is pre-existing code but worth noting for a future fix.

Suggested fix
 const issueDescription =
-  issue.description_html !== undefined || issue.description_html !== null
+  issue.description_html !== undefined && issue.description_html !== null
     ? issue.description_html != ""
       ? issue.description_html
       : "<p></p>"
     : undefined;

Or simplify with nullish checks:

-const issueDescription =
-  issue.description_html !== undefined || issue.description_html !== null
-    ? issue.description_html != ""
-      ? issue.description_html
-      : "<p></p>"
-    : undefined;
+const issueDescription =
+  issue.description_html != null
+    ? (issue.description_html !== "" ? issue.description_html : "<p></p>")
+    : undefined;
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fa1b4a1 and a95e008.

📒 Files selected for processing (4)
  • apps/web/core/components/editor/rich-text/description-input/root.tsx
  • apps/web/core/components/inbox/content/issue-root.tsx
  • apps/web/core/components/issues/issue-detail/main-content.tsx
  • apps/web/core/components/issues/peek-overview/issue-detail.tsx
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,mts,cts}

📄 CodeRabbit inference engine (.github/instructions/typescript.instructions.md)

**/*.{ts,tsx,mts,cts}: Use const type parameters for more precise literal inference in TypeScript 5.0+
Use the satisfies operator to validate types without widening them
Leverage inferred type predicates to reduce the need for explicit is return types in filter/check functions
Use NoInfer<T> utility to block inference for specific type arguments when they should be determined by other arguments
Utilize narrowing in switch(true) blocks for control flow analysis (TypeScript 5.3+)
Rely on narrowing from direct boolean comparisons for type guards
Trust preserved narrowing in closures when variables aren't modified after the check (TypeScript 5.4+)
Use constant indices to narrow object/array properties (TypeScript 5.5+)
Use standard ECMAScript decorators (Stage 3) instead of legacy experimentalDecorators
Use using declarations for explicit resource management with Disposable pattern instead of manual cleanup (TypeScript 5.2+)
Use with { type: "json" } for import attributes; avoid deprecated assert syntax (TypeScript 5.3/5.8+)
Use import type explicitly when importing types to ensure they are erased during compilation, respecting verbatimModuleSyntax flag
Use .ts, .mts, .cts extensions in import type statements (TypeScript 5.2+)
Use import type { Type } from "mod" with { "resolution-mode": "import" } for specific module resolution contexts (TypeScript 5.3+)
Use new iterator methods (map, filter, etc.) if targeting modern environments (TypeScript 5.6+)
Utilize new Set methods like union, intersection, etc., when available (TypeScript 5.5+)
Use Object.groupBy / Map.groupBy standard methods for grouping instead of external libraries (TypeScript 5.4+)
Use Promise.withResolvers() for creating promises with exposed resolve/reject functions (TypeScript 5.7+)
Use copying array methods (toSorted, toSpliced, with) for immutable array operations (TypeScript 5.2+)
Avoid accessing instance fields via super in classes (TypeScript 5....

Files:

  • apps/web/core/components/issues/issue-detail/main-content.tsx
  • apps/web/core/components/issues/peek-overview/issue-detail.tsx
  • apps/web/core/components/inbox/content/issue-root.tsx
  • apps/web/core/components/editor/rich-text/description-input/root.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Enable TypeScript strict mode and ensure all files are fully typed

Files:

  • apps/web/core/components/issues/issue-detail/main-content.tsx
  • apps/web/core/components/issues/peek-overview/issue-detail.tsx
  • apps/web/core/components/inbox/content/issue-root.tsx
  • apps/web/core/components/editor/rich-text/description-input/root.tsx
**/*.{js,jsx,ts,tsx,json,css}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier with Tailwind plugin for code formatting, run pnpm fix:format

Files:

  • apps/web/core/components/issues/issue-detail/main-content.tsx
  • apps/web/core/components/issues/peek-overview/issue-detail.tsx
  • apps/web/core/components/inbox/content/issue-root.tsx
  • apps/web/core/components/editor/rich-text/description-input/root.tsx
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,jsx,ts,tsx}: Use ESLint with shared config across packages, adhering to max warnings limits per package
Use camelCase for variable and function names, PascalCase for components and types
Use try-catch with proper error types and log errors appropriately

Files:

  • apps/web/core/components/issues/issue-detail/main-content.tsx
  • apps/web/core/components/issues/peek-overview/issue-detail.tsx
  • apps/web/core/components/inbox/content/issue-root.tsx
  • apps/web/core/components/editor/rich-text/description-input/root.tsx
🧠 Learnings (1)
📚 Learning: 2025-10-10T13:25:14.810Z
Learnt from: gakshita
Repo: makeplane/plane PR: 7949
File: apps/web/core/components/issues/issue-modal/form.tsx:183-189
Timestamp: 2025-10-10T13:25:14.810Z
Learning: In `apps/web/core/components/issues/issue-modal/form.tsx`, the form reset effect uses a `dataResetProperties` dependency array prop (default: []) to give parent components explicit control over when the form resets. Do not suggest adding the `data` prop itself to the dependency array, as this would cause unwanted resets on every render when the data object reference changes, disrupting user input. The current pattern is intentional and allows the parent to trigger resets only when specific conditions are met.

Applied to files:

  • apps/web/core/components/inbox/content/issue-root.tsx
  • apps/web/core/components/editor/rich-text/description-input/root.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Agent
  • GitHub Check: CodeQL analysis (javascript-typescript)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Build packages
🔇 Additional comments (5)
apps/web/core/components/editor/rich-text/description-input/root.tsx (2)

140-151: LGTM!

The submit handler correctly restructures the payload to pass both description_html and description_json to the onSubmit callback, aligning with the new API contract.


226-232: LGTM!

The onChange handler correctly captures description_json from the editor and stores it in the form state via setValue.

apps/web/core/components/issues/issue-detail/main-content.tsx (1)

137-143: LGTM!

The onSubmit handler correctly extracts description_html from the new object-based value parameter, aligning with the refactored DescriptionInput API.

apps/web/core/components/issues/peek-overview/issue-detail.tsx (1)

137-143: LGTM!

The onSubmit handler correctly extracts description_html from the new object-based value parameter, consistent with the refactored DescriptionInput API and other consumers in this PR.

apps/web/core/components/inbox/content/issue-root.tsx (1)

173-179: LGTM!

The onSubmit handler correctly extracts description_html from the new object-based value parameter, consistent with the refactored DescriptionInput API and other consumers in this PR.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants