From a95e0080d307f407c31366aea951c0adec75ae6e Mon Sep 17 00:00:00 2001
From: Aaryan Khandelwal
Date: Thu, 15 Jan 2026 15:53:38 +0530
Subject: [PATCH 1/2] refactor: description input component
---
.../rich-text/description-input/root.tsx | 23 +++++++++++++++----
.../components/inbox/content/issue-root.tsx | 2 +-
.../issues/issue-detail/main-content.tsx | 2 +-
.../issues/peek-overview/issue-detail.tsx | 2 +-
4 files changed, 21 insertions(+), 8 deletions(-)
diff --git a/apps/web/core/components/editor/rich-text/description-input/root.tsx b/apps/web/core/components/editor/rich-text/description-input/root.tsx
index 7c95e1ace5a..0d85100f76e 100644
--- a/apps/web/core/components/editor/rich-text/description-input/root.tsx
+++ b/apps/web/core/components/editor/rich-text/description-input/root.tsx
@@ -22,6 +22,7 @@ const workspaceService = new WorkspaceService();
type TFormData = {
id: string;
description_html: string;
+ description_json?: object;
isMigrationUpdate: boolean;
};
@@ -57,7 +58,13 @@ type Props = {
/**
* @description Submit handler, the actual function which will be called when the form is submitted
*/
- onSubmit: (value: string, isMigrationUpdate?: boolean) => Promise;
+ onSubmit: (
+ value: {
+ description_html: string;
+ description_json: object | undefined;
+ },
+ isMigrationUpdate?: boolean
+ ) => Promise;
/**
* @description Placeholder, if not provided, the placeholder will be the default placeholder
*/
@@ -97,13 +104,13 @@ export const DescriptionInput = observer(function DescriptionInput(props: Props)
entityId,
fileAssetType,
initialValue,
+ issueSequenceId,
onSubmit,
placeholder,
projectId,
setIsSubmitting,
swrDescription,
workspaceSlug,
- issueSequenceId,
} = props;
// states
const [localDescription, setLocalDescription] = useState({
@@ -132,7 +139,13 @@ export const DescriptionInput = observer(function DescriptionInput(props: Props)
// submit handler
const handleDescriptionFormSubmit = useCallback(
async (formData: TFormData) => {
- await onSubmit(formData.description_html, formData.isMigrationUpdate);
+ await onSubmit(
+ {
+ description_html: formData.description_html,
+ description_json: formData.description_json,
+ },
+ formData.isMigrationUpdate
+ );
},
[onSubmit]
);
@@ -203,7 +216,6 @@ export const DescriptionInput = observer(function DescriptionInput(props: Props)
editable={!disabled}
ref={editorRef}
id={entityId}
- issueSequenceId={issueSequenceId}
disabledExtensions={disabledExtensions}
initialValue={localDescription.description_html ?? ""}
value={swrDescription ?? null}
@@ -211,10 +223,11 @@ export const DescriptionInput = observer(function DescriptionInput(props: Props)
workspaceId={workspaceDetails.id}
projectId={projectId}
dragDropEnabled
- onChange={(_description, description_html, options) => {
+ onChange={(description_json, description_html, options) => {
setIsSubmitting("submitting");
onChange(description_html);
setValue("isMigrationUpdate", options?.isMigrationUpdate ?? false);
+ setValue("description_json", description_json);
hasUnsavedChanges.current = true;
debouncedFormSave();
}}
diff --git a/apps/web/core/components/inbox/content/issue-root.tsx b/apps/web/core/components/inbox/content/issue-root.tsx
index c09dc192f2e..9cc452b7f5f 100644
--- a/apps/web/core/components/inbox/content/issue-root.tsx
+++ b/apps/web/core/components/inbox/content/issue-root.tsx
@@ -173,7 +173,7 @@ export const InboxIssueMainContent = observer(function InboxIssueMainContent(pro
onSubmit={async (value, isMigrationUpdate) => {
if (!issue.id || !issue.project_id) return;
await issueOperations.update(workspaceSlug, issue.project_id, issue.id, {
- description_html: value,
+ description_html: value.description_html,
...(isMigrationUpdate ? { skip_activity: "true" } : {}),
});
}}
diff --git a/apps/web/core/components/issues/issue-detail/main-content.tsx b/apps/web/core/components/issues/issue-detail/main-content.tsx
index 78ac4e7507e..b1d3cba90f2 100644
--- a/apps/web/core/components/issues/issue-detail/main-content.tsx
+++ b/apps/web/core/components/issues/issue-detail/main-content.tsx
@@ -137,7 +137,7 @@ export const IssueMainContent = observer(function IssueMainContent(props: Props)
onSubmit={async (value, isMigrationUpdate) => {
if (!issue.id || !issue.project_id) return;
await issueOperations.update(workspaceSlug, issue.project_id, issue.id, {
- description_html: value,
+ description_html: value.description_html,
...(isMigrationUpdate ? { skip_activity: "true" } : {}),
});
}}
diff --git a/apps/web/core/components/issues/peek-overview/issue-detail.tsx b/apps/web/core/components/issues/peek-overview/issue-detail.tsx
index 3efdbf6418a..a08fdad4a49 100644
--- a/apps/web/core/components/issues/peek-overview/issue-detail.tsx
+++ b/apps/web/core/components/issues/peek-overview/issue-detail.tsx
@@ -137,7 +137,7 @@ export const PeekOverviewIssueDetails = observer(function PeekOverviewIssueDetai
onSubmit={async (value, isMigrationUpdate) => {
if (!issue.id || !issue.project_id) return;
await issueOperations.update(workspaceSlug, issue.project_id, issue.id, {
- description_html: value,
+ description_html: value.description_html,
...(isMigrationUpdate ? { skip_activity: "true" } : {}),
});
}}
From 0c37595acbd830e3172e31c800d6d5dc3d6c0f3b Mon Sep 17 00:00:00 2001
From: Aaryan Khandelwal
Date: Thu, 15 Jan 2026 16:06:04 +0530
Subject: [PATCH 2/2] fix: add missing prop to rich text editor
---
.../rich-text/description-input/root.tsx | 135 +++++++++---------
1 file changed, 66 insertions(+), 69 deletions(-)
diff --git a/apps/web/core/components/editor/rich-text/description-input/root.tsx b/apps/web/core/components/editor/rich-text/description-input/root.tsx
index 0d85100f76e..10c0a4744e1 100644
--- a/apps/web/core/components/editor/rich-text/description-input/root.tsx
+++ b/apps/web/core/components/editor/rich-text/description-input/root.tsx
@@ -205,77 +205,74 @@ export const DescriptionInput = observer(function DescriptionInput(props: Props)
if (!workspaceDetails) return null;
+ if (!localDescription.description_html) return ;
+
return (
- <>
- {localDescription.description_html ? (
- (
-
"}
- value={swrDescription ?? null}
- workspaceSlug={workspaceSlug}
- workspaceId={workspaceDetails.id}
- projectId={projectId}
- dragDropEnabled
- onChange={(description_json, description_html, options) => {
- setIsSubmitting("submitting");
- onChange(description_html);
- setValue("isMigrationUpdate", options?.isMigrationUpdate ?? false);
- setValue("description_json", description_json);
- hasUnsavedChanges.current = true;
- debouncedFormSave();
- }}
- placeholder={placeholder ?? ((isFocused, value) => t(getDescriptionPlaceholderI18n(isFocused, value)))}
- searchMentionCallback={async (payload) =>
- await workspaceService.searchEntity(workspaceSlug?.toString() ?? "", {
- ...payload,
- project_id: projectId,
- })
- }
- containerClassName={containerClassName}
- uploadFile={async (blockId, file) => {
- try {
- const { asset_id } = await uploadEditorAsset({
- blockId,
- data: {
- entity_identifier: entityId,
- entity_type: fileAssetType,
- },
- file,
- projectId,
- workspaceSlug,
- });
- return asset_id;
- } catch (error) {
- console.log("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 {
- throw new Error("Asset duplication failed. Please try again later.");
- }
- }}
- />
- )}
+ (
+ "}
+ value={swrDescription ?? null}
+ workspaceSlug={workspaceSlug}
+ workspaceId={workspaceDetails.id}
+ projectId={projectId}
+ dragDropEnabled
+ onChange={(description_json, description_html, options) => {
+ setIsSubmitting("submitting");
+ onChange(description_html);
+ setValue("isMigrationUpdate", options?.isMigrationUpdate ?? false);
+ setValue("description_json", description_json);
+ hasUnsavedChanges.current = true;
+ debouncedFormSave();
+ }}
+ placeholder={placeholder ?? ((isFocused, value) => t(getDescriptionPlaceholderI18n(isFocused, value)))}
+ searchMentionCallback={async (payload) =>
+ await workspaceService.searchEntity(workspaceSlug?.toString() ?? "", {
+ ...payload,
+ project_id: projectId,
+ })
+ }
+ containerClassName={containerClassName}
+ uploadFile={async (blockId, file) => {
+ try {
+ const { asset_id } = await uploadEditorAsset({
+ blockId,
+ data: {
+ entity_identifier: entityId,
+ entity_type: fileAssetType,
+ },
+ file,
+ projectId,
+ workspaceSlug,
+ });
+ return asset_id;
+ } catch (error) {
+ console.log("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 {
+ throw new Error("Asset duplication failed. Please try again later.");
+ }
+ }}
/>
- ) : (
-
)}
- >
+ />
);
});