[WIKI-874] refactor: description input component (#8544)

* refactor: description input component

* fix: add missing prop to rich text editor
This commit is contained in:
Aaryan Khandelwal 2026-03-05 19:37:36 +05:30 committed by GitHub
parent c3a9f99789
commit 2e429e5198
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 87 additions and 78 deletions

View file

@ -28,6 +28,7 @@ const workspaceService = new WorkspaceService();
type TFormData = { type TFormData = {
id: string; id: string;
description_html: string; description_html: string;
description_json?: object;
isMigrationUpdate: boolean; isMigrationUpdate: boolean;
}; };
@ -67,7 +68,13 @@ type Props = {
/** /**
* @description Submit handler, the actual function which will be called when the form is submitted * @description Submit handler, the actual function which will be called when the form is submitted
*/ */
onSubmit: (value: string, isMigrationUpdate?: boolean) => Promise<void>; onSubmit: (
value: {
description_html: string;
description_json: object | undefined;
},
isMigrationUpdate?: boolean
) => Promise<void>;
/** /**
* @description Placeholder, if not provided, the placeholder will be the default placeholder * @description Placeholder, if not provided, the placeholder will be the default placeholder
*/ */
@ -107,13 +114,13 @@ export const DescriptionInput = observer(function DescriptionInput(props: Props)
entityId, entityId,
fileAssetType, fileAssetType,
initialValue, initialValue,
issueSequenceId,
onSubmit, onSubmit,
placeholder, placeholder,
projectId, projectId,
setIsSubmitting, setIsSubmitting,
swrDescription, swrDescription,
workspaceSlug, workspaceSlug,
issueSequenceId,
} = props; } = props;
// states // states
const [localDescription, setLocalDescription] = useState<TFormData>({ const [localDescription, setLocalDescription] = useState<TFormData>({
@ -144,7 +151,13 @@ export const DescriptionInput = observer(function DescriptionInput(props: Props)
// submit handler // submit handler
const handleDescriptionFormSubmit = useCallback( const handleDescriptionFormSubmit = useCallback(
async (formData: TFormData) => { async (formData: TFormData) => {
await onSubmit(formData.description_html, formData.isMigrationUpdate); await onSubmit(
{
description_html: formData.description_html,
description_json: formData.description_json,
},
formData.isMigrationUpdate
);
// Update lastSavedContent after successful save // Update lastSavedContent after successful save
lastSavedContent.current = formData.description_html; lastSavedContent.current = formData.description_html;
}, },
@ -209,9 +222,9 @@ export const DescriptionInput = observer(function DescriptionInput(props: Props)
if (!workspaceDetails) return null; if (!workspaceDetails) return null;
if (!localDescription.description_html) return <DescriptionInputLoader />;
return ( return (
<>
{localDescription.description_html ? (
<Controller <Controller
name="description_html" name="description_html"
control={control} control={control}
@ -229,12 +242,12 @@ export const DescriptionInput = observer(function DescriptionInput(props: Props)
workspaceId={workspaceDetails.id} workspaceId={workspaceDetails.id}
projectId={projectId} projectId={projectId}
dragDropEnabled dragDropEnabled
onChange={(_description, description_html, options) => { onChange={(description_json, description_html, options) => {
// Skip if content hasn't actually changed (handles editor normalization on init)
if (description_html === lastSavedContent.current) return; if (description_html === lastSavedContent.current) return;
setIsSubmitting("submitting"); setIsSubmitting("submitting");
onChange(description_html); onChange(description_html);
setValue("isMigrationUpdate", options?.isMigrationUpdate ?? false); setValue("isMigrationUpdate", !!options?.isMigrationUpdate);
setValue("description_json", description_json);
hasUnsavedChanges.current = true; hasUnsavedChanges.current = true;
debouncedFormSave(); debouncedFormSave();
}} }}
@ -280,9 +293,5 @@ export const DescriptionInput = observer(function DescriptionInput(props: Props)
/> />
)} )}
/> />
) : (
<DescriptionInputLoader />
)}
</>
); );
}); });

View file

@ -180,7 +180,7 @@ export const InboxIssueMainContent = observer(function InboxIssueMainContent(pro
onSubmit={async (value, isMigrationUpdate) => { onSubmit={async (value, isMigrationUpdate) => {
if (!issue.id || !issue.project_id) return; if (!issue.id || !issue.project_id) return;
await issueOperations.update(workspaceSlug, issue.project_id, issue.id, { await issueOperations.update(workspaceSlug, issue.project_id, issue.id, {
description_html: value, description_html: value.description_html,
...(isMigrationUpdate ? { skip_activity: "true" } : {}), ...(isMigrationUpdate ? { skip_activity: "true" } : {}),
}); });
}} }}

View file

@ -144,7 +144,7 @@ export const IssueMainContent = observer(function IssueMainContent(props: Props)
onSubmit={async (value, isMigrationUpdate) => { onSubmit={async (value, isMigrationUpdate) => {
if (!issue.id || !issue.project_id) return; if (!issue.id || !issue.project_id) return;
await issueOperations.update(workspaceSlug, issue.project_id, issue.id, { await issueOperations.update(workspaceSlug, issue.project_id, issue.id, {
description_html: value, description_html: value.description_html,
...(isMigrationUpdate ? { skip_activity: "true" } : {}), ...(isMigrationUpdate ? { skip_activity: "true" } : {}),
}); });
}} }}

View file

@ -144,7 +144,7 @@ export const PeekOverviewIssueDetails = observer(function PeekOverviewIssueDetai
onSubmit={async (value, isMigrationUpdate) => { onSubmit={async (value, isMigrationUpdate) => {
if (!issue.id || !issue.project_id) return; if (!issue.id || !issue.project_id) return;
await issueOperations.update(workspaceSlug, issue.project_id, issue.id, { await issueOperations.update(workspaceSlug, issue.project_id, issue.id, {
description_html: value, description_html: value.description_html,
...(isMigrationUpdate ? { skip_activity: "true" } : {}), ...(isMigrationUpdate ? { skip_activity: "true" } : {}),
}); });
}} }}