From 945a75e18b489e6b5a1224beb3d0112eaa6eb346 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Sat, 3 Dec 2022 19:11:07 +0530 Subject: [PATCH 1/2] feat: lexical integrated --- .../command-palette/addAsSubIssue.tsx | 214 +++++++++--------- apps/app/components/lexical/viewer.tsx | 10 +- .../CreateUpdateIssueModal/SelectAssignee.tsx | 2 +- .../CreateUpdateIssueModal/SelectCycles.tsx | 2 +- .../CreateUpdateIssueModal/SelectLabels.tsx | 2 +- .../SelectParentIssue.tsx | 47 ++++ .../SelectParentIssues.tsx | 66 ------ .../CreateUpdateIssueModal/SelectPriority.tsx | 6 +- .../issues/CreateUpdateIssueModal/index.tsx | 65 +++++- .../project/issues/IssuesListModal.tsx | 134 +++++++++++ .../project/issues/ListView/index.tsx | 15 +- .../issues/issue-detail/activity/index.tsx | 22 +- .../projects/[projectId]/issues/[issueId].tsx | 46 ++-- .../pages/projects/[projectId]/members.tsx | 2 +- apps/app/pages/workspace/members.tsx | 4 +- apps/app/ui/CustomListbox/index.tsx | 2 +- apps/app/ui/CustomListbox/types.d.ts | 2 +- apps/app/ui/SearchListbox/index.tsx | 16 +- 18 files changed, 417 insertions(+), 240 deletions(-) create mode 100644 apps/app/components/project/issues/CreateUpdateIssueModal/SelectParentIssue.tsx delete mode 100644 apps/app/components/project/issues/CreateUpdateIssueModal/SelectParentIssues.tsx create mode 100644 apps/app/components/project/issues/IssuesListModal.tsx diff --git a/apps/app/components/command-palette/addAsSubIssue.tsx b/apps/app/components/command-palette/addAsSubIssue.tsx index 41c3e3d28..11cfcc907 100644 --- a/apps/app/components/command-palette/addAsSubIssue.tsx +++ b/apps/app/components/command-palette/addAsSubIssue.tsx @@ -1,3 +1,4 @@ +// react import React, { useState } from "react"; // swr import { mutate } from "swr"; @@ -5,18 +6,18 @@ import { mutate } from "swr"; import { useForm } from "react-hook-form"; // headless ui import { Combobox, Dialog, Transition } from "@headlessui/react"; +// services +import issuesServices from "lib/services/issues.services"; // hooks import useUser from "lib/hooks/useUser"; // icons -import { MagnifyingGlassIcon } from "@heroicons/react/20/solid"; -import { FolderIcon } from "@heroicons/react/24/outline"; +import { RectangleStackIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline"; // commons import { classNames } from "constants/common"; // types import { IIssue, IssueResponse } from "types"; -import { Button } from "ui"; -import { PROJECT_ISSUES_DETAILS, PROJECT_ISSUES_LIST } from "constants/fetch-keys"; -import issuesServices from "lib/services/issues.services"; +// constants +import { PROJECT_ISSUES_LIST } from "constants/fetch-keys"; type Props = { isOpen: boolean; @@ -41,18 +42,13 @@ const AddAsSubIssue: React.FC = ({ isOpen, setIsOpen, parentId }) => { []; const { - register, formState: { errors, isSubmitting }, - handleSubmit, - control, reset, - setError, } = useForm(); const handleCommandPaletteClose = () => { setIsOpen(false); setQuery(""); - reset(); }; const addAsSubIssue = (issueId: string) => { @@ -78,118 +74,112 @@ const AddAsSubIssue: React.FC = ({ isOpen, setIsOpen, parentId }) => { }; return ( - <> - setQuery("")} appear> - + setQuery("")} appear> + + +
+ + +
-
- + + +
+
-
- - - { - // const { url, onClick } = item; - // if (url) router.push(url); - // else if (onClick) onClick(); - // handleCommandPaletteClose(); - // }} + -
- 0 && ( + <> +
  • + {query === "" && ( +

    + Issues +

    + )} +
      + {filteredIssues.map((issue) => { + if ( + (issue.parent === "" || issue.parent === null) && + issue.id !== parentId + ) + return ( + + classNames( + "flex items-center gap-2 cursor-pointer select-none rounded-md px-3 py-2", + active ? "bg-gray-900 bg-opacity-5 text-gray-900" : "" + ) + } + onClick={() => { + addAsSubIssue(issue.id); + setIsOpen(false); + }} + > + + {issue.name} + + ); + })} +
    +
  • + + )} + + + {query !== "" && filteredIssues.length === 0 && ( +
    +
    - - - {filteredIssues.length > 0 && ( - <> -
  • - {query === "" && ( -

    - Issues -

    - )} -
      - {filteredIssues.map((issue) => { - if (issue.parent === "" || issue.parent === null) - return ( - - classNames( - "flex items-center gap-2 cursor-pointer select-none rounded-md px-3 py-2", - active ? "bg-gray-900 bg-opacity-5 text-gray-900" : "" - ) - } - onClick={() => { - addAsSubIssue(issue.id); - setIsOpen(false); - }} - > - - {issue.name} - - ); - })} -
    -
  • - - )} -
    - - {query !== "" && filteredIssues.length === 0 && ( -
    -
    - )} - - - -
    -
    -
    - + )} + + + + +
    +
    ); }; diff --git a/apps/app/components/lexical/viewer.tsx b/apps/app/components/lexical/viewer.tsx index 83be573c0..9ea988126 100644 --- a/apps/app/components/lexical/viewer.tsx +++ b/apps/app/components/lexical/viewer.tsx @@ -1,4 +1,3 @@ -import { FC } from "react"; import { LexicalComposer } from "@lexical/react/LexicalComposer"; import { ContentEditable } from "@lexical/react/LexicalContentEditable"; import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin"; @@ -17,14 +16,11 @@ import { getValidatedValue } from "./helpers/editor"; import LexicalErrorBoundary from "@lexical/react/LexicalErrorBoundary"; export interface RichTextViewerProps { - id: string; value: string; + id: string; } -const RichTextViewer: FC = (props) => { - // props - const { value, id } = props; - +const RichTextViewer: React.FC = ({ value, id }) => { return ( = (props) => {
    + } ErrorBoundary={LexicalErrorBoundary} placeholder={ diff --git a/apps/app/components/project/issues/CreateUpdateIssueModal/SelectAssignee.tsx b/apps/app/components/project/issues/CreateUpdateIssueModal/SelectAssignee.tsx index bee25039f..376ab65e6 100644 --- a/apps/app/components/project/issues/CreateUpdateIssueModal/SelectAssignee.tsx +++ b/apps/app/components/project/issues/CreateUpdateIssueModal/SelectAssignee.tsx @@ -44,7 +44,7 @@ const SelectAssignee: React.FC = ({ control }) => { multiple={true} value={value} onChange={onChange} - icon={} + icon={} /> )} /> diff --git a/apps/app/components/project/issues/CreateUpdateIssueModal/SelectCycles.tsx b/apps/app/components/project/issues/CreateUpdateIssueModal/SelectCycles.tsx index 7987bff8d..6553c205a 100644 --- a/apps/app/components/project/issues/CreateUpdateIssueModal/SelectCycles.tsx +++ b/apps/app/components/project/issues/CreateUpdateIssueModal/SelectCycles.tsx @@ -33,7 +33,7 @@ const SelectSprint: React.FC = ({ control, setIsOpen }) => { <>
    - + {cycles?.find((i) => i.id.toString() === value?.toString())?.name ?? "Cycle"} diff --git a/apps/app/components/project/issues/CreateUpdateIssueModal/SelectLabels.tsx b/apps/app/components/project/issues/CreateUpdateIssueModal/SelectLabels.tsx index ede265c98..a7ef75203 100644 --- a/apps/app/components/project/issues/CreateUpdateIssueModal/SelectLabels.tsx +++ b/apps/app/components/project/issues/CreateUpdateIssueModal/SelectLabels.tsx @@ -83,7 +83,7 @@ const SelectLabels: React.FC = ({ control }) => { <>
    - + {value && value.length > 0 ? value.map((id) => issueLabels?.find((i) => i.id === id)?.name).join(", ") diff --git a/apps/app/components/project/issues/CreateUpdateIssueModal/SelectParentIssue.tsx b/apps/app/components/project/issues/CreateUpdateIssueModal/SelectParentIssue.tsx new file mode 100644 index 000000000..8a4b7af64 --- /dev/null +++ b/apps/app/components/project/issues/CreateUpdateIssueModal/SelectParentIssue.tsx @@ -0,0 +1,47 @@ +import React, { useState } from "react"; +// react hook form +import { Controller, Control } from "react-hook-form"; +// hooks +import useUser from "lib/hooks/useUser"; +// types +import type { IIssue } from "types"; +// icons +import { UserIcon } from "@heroicons/react/24/outline"; +// components +import IssuesListModal from "components/project/issues/IssuesListModal"; + +type Props = { + control: Control; +}; + +const SelectParent: React.FC = ({ control }) => { + const [isIssueListModalOpen, setIsIssueListModalOpen] = useState(false); + + const { issues } = useUser(); + + return ( + ( + <> + setIsIssueListModalOpen(false)} + onChange={onChange} + issues={issues} + /> + + + )} + /> + ); +}; + +export default SelectParent; diff --git a/apps/app/components/project/issues/CreateUpdateIssueModal/SelectParentIssues.tsx b/apps/app/components/project/issues/CreateUpdateIssueModal/SelectParentIssues.tsx deleted file mode 100644 index 83db0b895..000000000 --- a/apps/app/components/project/issues/CreateUpdateIssueModal/SelectParentIssues.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import React from "react"; -// react hook form -import { Controller } from "react-hook-form"; -// hooks -import useUser from "lib/hooks/useUser"; -// types -import type { IIssue } from "types"; -import type { Control } from "react-hook-form"; -import { UserIcon } from "@heroicons/react/24/outline"; - -type Props = { - control: Control; -}; - -import { SearchListbox } from "ui"; - -const SelectParent: React.FC = ({ control }) => { - const { issues: projectIssues } = useUser(); - - const getSelectedIssueKey = (issueId: string | undefined) => { - const identifier = projectIssues?.results?.find((i) => i.id.toString() === issueId?.toString()) - ?.project_detail?.identifier; - - const sequenceId = projectIssues?.results?.find( - (i) => i.id.toString() === issueId?.toString() - )?.sequence_id; - - if (issueId) return `${identifier}-${sequenceId}`; - else return "Parent issue"; - }; - - return ( - ( - { - return { - value: issue.id, - display: issue.name, - element: ( -
    -
    - {`${getSelectedIssueKey(issue.id)}`} - {issue.name} -
    -
    - ), - }; - })} - value={value} - width="xs" - buttonClassName="max-h-30 overflow-y-scroll" - optionsClassName="max-h-30 overflow-y-scroll" - onChange={onChange} - icon={} - /> - )} - /> - ); -}; - -export default SelectParent; diff --git a/apps/app/components/project/issues/CreateUpdateIssueModal/SelectPriority.tsx b/apps/app/components/project/issues/CreateUpdateIssueModal/SelectPriority.tsx index 2452908cd..b53dfe777 100644 --- a/apps/app/components/project/issues/CreateUpdateIssueModal/SelectPriority.tsx +++ b/apps/app/components/project/issues/CreateUpdateIssueModal/SelectPriority.tsx @@ -28,8 +28,10 @@ const SelectPriority: React.FC = ({ control }) => { <>
    - - {value ?? "Priority"} + + + {value && value !== "" ? value : "Priority"} + = { + project: "", name: "", description: "", + state: "", + sprints: "", + priority: "", + labels_list: [], }; const CreateUpdateIssuesModal: React.FC = ({ @@ -65,6 +71,16 @@ const CreateUpdateIssuesModal: React.FC = ({ const [mostSimilarIssue, setMostSimilarIssue] = useState(); + // const [issueDescriptionValue, setIssueDescriptionValue] = useState(""); + // const handleDescriptionChange: any = (value: any) => { + // console.log(value); + // setIssueDescriptionValue(value); + // }; + + const RichTextEditor = dynamic(() => import("components/lexical/editor"), { + ssr: false, + }); + const router = useRouter(); const handleClose = () => { @@ -93,6 +109,7 @@ const CreateUpdateIssuesModal: React.FC = ({ setError, control, watch, + setValue, } = useForm({ defaultValues, }); @@ -159,6 +176,7 @@ const CreateUpdateIssuesModal: React.FC = ({ if (!activeWorkspace || !activeProject) return; const payload: Partial = { ...formData, + description: JSON.stringify(formData.description), target_date: formData.target_date ? renderDateFormat(formData.target_date ?? "") : null, }; if (!data) { @@ -261,6 +279,8 @@ const CreateUpdateIssuesModal: React.FC = ({ return () => setMostSimilarIssue(undefined); }, []); + // console.log(watch("parent")); + return ( <> {activeProject && ( @@ -373,13 +393,20 @@ const CreateUpdateIssuesModal: React.FC = ({ )}
    -