-
Notifications
You must be signed in to change notification settings - Fork 3.6k
[WEB-2388] chore: workspace draft issue improvements #5808
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,7 +7,7 @@ import { useForm } from "react-hook-form"; | |
| // editor | ||
| import { EditorRefApi } from "@plane/editor"; | ||
| // types | ||
| import type { TIssue, ISearchIssueResponse } from "@plane/types"; | ||
| import type { TIssue, ISearchIssueResponse, TWorkspaceDraftIssue } from "@plane/types"; | ||
| // hooks | ||
| import { Button, ToggleSwitch, TOAST_TYPE, setToast } from "@plane/ui"; | ||
| // components | ||
|
|
@@ -26,7 +26,7 @@ import { getChangedIssuefields } from "@/helpers/issue.helper"; | |
| import { getTabIndex } from "@/helpers/tab-indices.helper"; | ||
| // hooks | ||
| import { useIssueModal } from "@/hooks/context/use-issue-modal"; | ||
| import { useIssueDetail, useProject, useProjectState } from "@/hooks/store"; | ||
| import { useIssueDetail, useProject, useProjectState, useWorkspaceDraftIssues } from "@/hooks/store"; | ||
| import { usePlatformOS } from "@/hooks/use-platform-os"; | ||
| import { useProjectIssueProperties } from "@/hooks/use-project-issue-properties"; | ||
| // plane web components | ||
|
|
@@ -59,6 +59,7 @@ export interface IssueFormProps { | |
| onSubmit: (values: Partial<TIssue>, is_draft_issue?: boolean) => Promise<void>; | ||
| projectId: string; | ||
| isDraft: boolean; | ||
| moveToIssue?: boolean; | ||
| } | ||
|
|
||
| export const IssueFormRoot: FC<IssueFormProps> = observer((props) => { | ||
|
|
@@ -72,6 +73,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => { | |
| isCreateMoreToggleEnabled, | ||
| onCreateMoreToggleChange, | ||
| isDraft, | ||
| moveToIssue, | ||
| } = props; | ||
|
|
||
| // states | ||
|
|
@@ -91,6 +93,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => { | |
| const { getIssueTypeIdOnProjectChange, getActiveAdditionalPropertiesLength, handlePropertyValuesValidation } = | ||
| useIssueModal(); | ||
| const { isMobile } = usePlatformOS(); | ||
| const { moveIssue } = useWorkspaceDraftIssues(); | ||
|
|
||
| const { | ||
| issue: { getIssueById }, | ||
|
|
@@ -400,7 +403,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => { | |
| Discard | ||
| </Button> | ||
| <Button | ||
| variant="primary" | ||
| variant={moveToIssue ? "neutral-primary" : "primary"} | ||
| type="submit" | ||
| size="sm" | ||
| ref={submitBtnRef} | ||
|
|
@@ -417,6 +420,19 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => { | |
| ? "Create draft issue" | ||
| : "Create"} | ||
| </Button> | ||
| {moveToIssue && ( | ||
| <Button | ||
| variant="primary" | ||
| type="button" | ||
| size="sm" | ||
| loading={isSubmitting} | ||
| onClick={() => | ||
|
Comment on lines
+428
to
+429
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use Dedicated Loading State for the "Add to project" Button The Introduce a separate loading state for the +const [isMovingIssue, setIsMovingIssue] = useState(false);
...
<Button
variant="primary"
type="button"
size="sm"
- loading={isSubmitting}
+ loading={isMovingIssue}
onClick={async () => {
+ setIsMovingIssue(true);
if (data?.id && data) {
- moveIssue(workspaceSlug.toString(), data.id, data as TWorkspaceDraftIssue);
+ await moveIssue(workspaceSlug.toString(), data.id, data as TWorkspaceDraftIssue);
}
+ setIsMovingIssue(false);
}}
>
Add to project
</Button>
|
||
| data?.id && data && moveIssue(workspaceSlug.toString(), data?.id, data as TWorkspaceDraftIssue) | ||
| } | ||
|
Comment on lines
+429
to
+431
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add Error Handling to the Currently, the Wrap the onClick={async () => {
setIsMovingIssue(true);
try {
if (data?.id && data) {
await moveIssue(workspaceSlug.toString(), data.id, data as TWorkspaceDraftIssue);
}
} catch (error) {
setToast({
type: TOAST_TYPE.ERROR,
title: "Error!",
message: "Failed to move the issue to the project. Please try again.",
});
} finally {
setIsMovingIssue(false);
}
}}
|
||
| > | ||
| Add to project | ||
| </Button> | ||
| )} | ||
|
Comment on lines
+423
to
+435
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure Type Safety When Casting In the To address this, explicitly construct a onClick={() => {
if (data?.id && data) {
- moveIssue(workspaceSlug.toString(), data.id, data as TWorkspaceDraftIssue);
+ const draftIssue: TWorkspaceDraftIssue = {
+ id: data.id,
+ // Add all required fields here, ensuring they come from 'data' and are not undefined
+ // For example:
+ name: data.name ?? '',
+ description_html: data.description_html ?? '<p></p>',
+ // Include other necessary fields
+ };
+ moveIssue(workspaceSlug.toString(), data.id, draftIssue);
}
}}
|
||
| </div> | ||
| </div> | ||
| </div> | ||
|
|
||
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.
Ensure
description_htmlis properly sanitized before including in the response.To prevent potential XSS vulnerabilities, verify that
description_htmlis sanitized before being sent to the client. This helps protect against any malicious content that may have been injected.