forked from github/plane
[WEB-496] fix: issue comment (#3796)
* fix: issue comment empty string and on enter functionality * fix: empty html tag validation added * fix: purifying dom contents before saving comments --------- Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
This commit is contained in:
committed by
GitHub
parent
e1f13af084
commit
5c089f0223
@@ -11,6 +11,8 @@ import { TIssueComment } from "@plane/types";
|
||||
// icons
|
||||
import { Globe2, Lock } from "lucide-react";
|
||||
import { useMention, useWorkspace } from "hooks/store";
|
||||
// helpers
|
||||
import { isEmptyHtmlString } from "helpers/string.helper";
|
||||
|
||||
const fileService = new FileService();
|
||||
|
||||
@@ -51,10 +53,10 @@ export const IssueCommentCreate: FC<TIssueCommentCreate> = (props) => {
|
||||
const {
|
||||
handleSubmit,
|
||||
control,
|
||||
watch,
|
||||
formState: { isSubmitting },
|
||||
reset,
|
||||
watch,
|
||||
} = useForm<Partial<TIssueComment>>({ defaultValues: { comment_html: "" } });
|
||||
} = useForm<Partial<TIssueComment>>({ defaultValues: { comment_html: "<p></p>" } });
|
||||
|
||||
const onSubmit = async (formData: Partial<TIssueComment>) => {
|
||||
await activityOperations.createComment(formData).finally(() => {
|
||||
@@ -63,14 +65,19 @@ export const IssueCommentCreate: FC<TIssueCommentCreate> = (props) => {
|
||||
});
|
||||
};
|
||||
|
||||
const isEmpty =
|
||||
watch("comment_html") === "" ||
|
||||
watch("comment_html")?.trim() === "" ||
|
||||
watch("comment_html") === "<p></p>" ||
|
||||
isEmptyHtmlString(watch("comment_html") ?? "");
|
||||
|
||||
return (
|
||||
<div
|
||||
// onKeyDown={(e) => {
|
||||
// if (e.key === "Enter" && !e.shiftKey) {
|
||||
// e.preventDefault();
|
||||
// // handleSubmit(onSubmit)(e);
|
||||
// }
|
||||
// }}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter" && !e.shiftKey && !isEmpty) {
|
||||
handleSubmit(onSubmit)(e);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Controller
|
||||
name="access"
|
||||
@@ -81,15 +88,12 @@ export const IssueCommentCreate: FC<TIssueCommentCreate> = (props) => {
|
||||
control={control}
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<LiteTextEditorWithRef
|
||||
onEnterKeyPress={(e) => {
|
||||
handleSubmit(onSubmit)(e);
|
||||
}}
|
||||
cancelUploadImage={fileService.cancelUpload}
|
||||
uploadFile={fileService.getUploadFileFunction(workspaceSlug as string)}
|
||||
deleteFile={fileService.getDeleteImageFunction(workspaceId)}
|
||||
restoreFile={fileService.getRestoreImageFunction(workspaceId)}
|
||||
ref={editorRef}
|
||||
value={value ?? ""}
|
||||
value={!value ? "<p></p>" : value}
|
||||
customClassName="p-2"
|
||||
editorContentCustomClassNames="min-h-[35px]"
|
||||
debouncedUpdatesEnabled={false}
|
||||
@@ -105,7 +109,7 @@ export const IssueCommentCreate: FC<TIssueCommentCreate> = (props) => {
|
||||
}
|
||||
submitButton={
|
||||
<Button
|
||||
disabled={isSubmitting || watch("comment_html") === ""}
|
||||
disabled={isSubmitting || isEmpty}
|
||||
variant="primary"
|
||||
type="submit"
|
||||
className="!px-2.5 !py-1.5 !text-xs"
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
PROJECT_ISSUES_LIST_WITH_PARAMS,
|
||||
VIEW_ISSUES,
|
||||
} from "constants/fetch-keys";
|
||||
import * as DOMPurify from 'dompurify';
|
||||
|
||||
export const addSpaceIfCamelCase = (str: string) => {
|
||||
if (str === undefined || str === null) return "";
|
||||
@@ -171,10 +172,10 @@ export const getFetchKeysForIssueMutation = (options: {
|
||||
const ganttFetchKey = cycleId
|
||||
? { ganttFetchKey: CYCLE_ISSUES_WITH_PARAMS(cycleId.toString(), ganttParams) }
|
||||
: moduleId
|
||||
? { ganttFetchKey: MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), ganttParams) }
|
||||
: viewId
|
||||
? { ganttFetchKey: VIEW_ISSUES(viewId.toString(), viewGanttParams) }
|
||||
: { ganttFetchKey: PROJECT_ISSUES_LIST_WITH_PARAMS(projectId?.toString() ?? "", ganttParams) };
|
||||
? { ganttFetchKey: MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), ganttParams) }
|
||||
: viewId
|
||||
? { ganttFetchKey: VIEW_ISSUES(viewId.toString(), viewGanttParams) }
|
||||
: { ganttFetchKey: PROJECT_ISSUES_LIST_WITH_PARAMS(projectId?.toString() ?? "", ganttParams) };
|
||||
|
||||
return {
|
||||
...ganttFetchKey,
|
||||
@@ -224,3 +225,10 @@ export const checkEmailValidity = (email: string): boolean => {
|
||||
|
||||
return isEmailValid;
|
||||
};
|
||||
|
||||
export const isEmptyHtmlString = (htmlString: string) => {
|
||||
// Remove HTML tags using regex
|
||||
const cleanText = DOMPurify.sanitize(htmlString, { ALLOWED_TAGS: [] });
|
||||
// Trim the string and check if it's empty
|
||||
return cleanText.trim() === "";
|
||||
};
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"clsx": "^2.0.0",
|
||||
"cmdk": "^0.2.0",
|
||||
"date-fns": "^2.30.0",
|
||||
"dompurify": "^3.0.9",
|
||||
"dotenv": "^16.0.3",
|
||||
"js-cookie": "^3.0.1",
|
||||
"lodash": "^4.17.21",
|
||||
@@ -61,6 +62,7 @@
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@types/js-cookie": "^3.0.2",
|
||||
"@types/lodash": "^4.14.202",
|
||||
"@types/node": "18.0.6",
|
||||
|
||||
Reference in New Issue
Block a user