From 9c8c7f1ddacc2baca70c9c3f7f1264fe1e1403a7 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com> Date: Tue, 14 Feb 2023 14:35:14 +0530 Subject: [PATCH 1/4] fix: mac text copy fix (#277) --- apps/app/components/command-palette/command-pallette.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app/components/command-palette/command-pallette.tsx b/apps/app/components/command-palette/command-pallette.tsx index 678e17d46..cb4f398b9 100644 --- a/apps/app/components/command-palette/command-pallette.tsx +++ b/apps/app/components/command-palette/command-pallette.tsx @@ -105,7 +105,7 @@ export const CommandPalette: React.FC = () => { if ((e.ctrlKey || e.metaKey) && (e.key === "k" || e.key === "K")) { e.preventDefault(); setIsPaletteOpen(true); - } else if (e.ctrlKey && (e.key === "c" || e.key === "C")) { + } else if ((e.ctrlKey || e.metaKey) && (e.key === "c" || e.key === "C")) { if (e.altKey) { e.preventDefault(); if (!router.query.issueId) return; From e53ff4c02e7c9dd42f88f422df49fd1b5267273a Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Tue, 14 Feb 2023 14:46:48 +0530 Subject: [PATCH 2/4] feat: state description in settings (#275) * chore: removed minor bugs * feat: state description in settings * feat: group by assignee --- .../core/board-view/board-header.tsx | 133 +++++++------- .../core/board-view/single-board.tsx | 12 +- .../components/core/list-view/single-list.tsx | 16 +- .../issues/sidebar-select/cycle.tsx | 6 +- .../issues/sidebar-select/module.tsx | 6 +- apps/app/components/issues/sidebar.tsx | 45 +++-- .../components/modules/single-module-card.tsx | 162 ++++++------------ apps/app/components/states/single-state.tsx | 7 +- .../app/components/ui/{avatar => }/avatar.tsx | 2 +- apps/app/components/ui/avatar/index.ts | 1 - apps/app/components/ui/index.ts | 3 +- apps/app/constants/issue.ts | 1 + .../projects/[projectId]/settings/states.tsx | 2 +- 13 files changed, 188 insertions(+), 208 deletions(-) rename apps/app/components/ui/{avatar => }/avatar.tsx (96%) delete mode 100644 apps/app/components/ui/avatar/index.ts diff --git a/apps/app/components/core/board-view/board-header.tsx b/apps/app/components/core/board-view/board-header.tsx index 3a7753366..9fe51b793 100644 --- a/apps/app/components/core/board-view/board-header.tsx +++ b/apps/app/components/core/board-view/board-header.tsx @@ -12,80 +12,97 @@ import { // helpers import { addSpaceIfCamelCase } from "helpers/string.helper"; // types -import { IIssue } from "types"; +import { IIssue, IProjectMember, NestedKeyOf } from "types"; type Props = { - isCollapsed: boolean; - setIsCollapsed: React.Dispatch>; groupedByIssues: { [key: string]: IIssue[]; }; + selectedGroup: NestedKeyOf | null; groupTitle: string; - createdBy: string | null; bgColor?: string; addIssueToState: () => void; + members: IProjectMember[] | undefined; + isCollapsed: boolean; + setIsCollapsed: React.Dispatch>; }; export const BoardHeader: React.FC = ({ - isCollapsed, - setIsCollapsed, groupedByIssues, + selectedGroup, groupTitle, - createdBy, bgColor, addIssueToState, -}) => ( -
-
-
-

{ + const createdBy = + selectedGroup === "created_by" + ? members?.find((m) => m.member.id === groupTitle)?.member.first_name ?? "loading..." + : null; + + let assignees: any; + if (selectedGroup === "assignees") { + assignees = groupTitle.split(","); + assignees = assignees + .map((a: string) => members?.find((m) => m.member.id === a)?.member.first_name) + .join(", "); + } + + return ( +
+
+
- {groupTitle === null || groupTitle === "null" - ? "None" - : createdBy - ? createdBy - : addSpaceIfCamelCase(groupTitle)} -

- {groupedByIssues[groupTitle].length} +

+ {selectedGroup === "created_by" + ? createdBy + : selectedGroup === "assignees" + ? assignees + : addSpaceIfCamelCase(groupTitle)} +

+ {groupedByIssues[groupTitle].length} +
+
+ +
+ +
- -
- - -
- -); + ); +}; diff --git a/apps/app/components/core/board-view/single-board.tsx b/apps/app/components/core/board-view/single-board.tsx index e7cb49798..e0e790da5 100644 --- a/apps/app/components/core/board-view/single-board.tsx +++ b/apps/app/components/core/board-view/single-board.tsx @@ -55,11 +55,6 @@ export const SingleBoard: React.FC = ({ const [properties] = useIssuesProperties(workspaceSlug as string, projectId as string); - const createdBy = - selectedGroup === "created_by" - ? members?.find((m) => m.member.id === groupTitle)?.member.first_name ?? "loading..." - : null; - if (selectedGroup === "priority") groupTitle === "high" ? (bgColor = "#dc2626") @@ -77,11 +72,12 @@ export const SingleBoard: React.FC = ({ {(provided, snapshot) => ( @@ -97,7 +93,9 @@ export const SingleBoard: React.FC = ({ key={issue.id} draggableId={issue.id} index={index} - isDragDisabled={isNotAllowed || selectedGroup === "created_by"} + isDragDisabled={ + isNotAllowed || selectedGroup === "created_by" || selectedGroup === "assignees" + } > {(provided, snapshot) => ( = ({ const createdBy = selectedGroup === "created_by" - ? members?.find((m) => m.member.id === groupTitle)?.member.first_name ?? "loading..." + ? members?.find((m) => m.member.id === groupTitle)?.member.first_name ?? "Loading..." : null; + let assignees: any; + if (selectedGroup === "assignees") { + assignees = groupTitle.split(","); + assignees = assignees + .map((a: string) => members?.find((m) => m.member.id === a)?.member.first_name) + .join(", "); + } + return ( {({ open }) => ( @@ -67,10 +75,10 @@ export const SingleList: React.FC = ({ {selectedGroup !== null ? (

- {groupTitle === null || groupTitle === "null" - ? "None" - : createdBy + {selectedGroup === "created_by" ? createdBy + : selectedGroup === "assignees" + ? assignees : addSpaceIfCamelCase(groupTitle)}

) : ( diff --git a/apps/app/components/issues/sidebar-select/cycle.tsx b/apps/app/components/issues/sidebar-select/cycle.tsx index 353bc5121..b1243fe98 100644 --- a/apps/app/components/issues/sidebar-select/cycle.tsx +++ b/apps/app/components/issues/sidebar-select/cycle.tsx @@ -82,14 +82,14 @@ export const SidebarCycleSelect: React.FC = ({ {cycles ? ( cycles.length > 0 ? ( <> - - None - {cycles.map((option) => ( {option.name} ))} + + None + ) : (
No cycles found
diff --git a/apps/app/components/issues/sidebar-select/module.tsx b/apps/app/components/issues/sidebar-select/module.tsx index e57688887..44bef4d62 100644 --- a/apps/app/components/issues/sidebar-select/module.tsx +++ b/apps/app/components/issues/sidebar-select/module.tsx @@ -81,14 +81,14 @@ export const SidebarModuleSelect: React.FC = ({ {modules ? ( modules.length > 0 ? ( <> - - None - {modules.map((option) => ( {option.name} ))} + + None + ) : (
No modules found
diff --git a/apps/app/components/issues/sidebar.tsx b/apps/app/components/issues/sidebar.tsx index c321f0a31..3ab331244 100644 --- a/apps/app/components/issues/sidebar.tsx +++ b/apps/app/components/issues/sidebar.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useState } from "react"; +import React, { useCallback, useEffect, useState } from "react"; import { useRouter } from "next/router"; @@ -144,6 +144,12 @@ export const IssueDetailsSidebar: React.FC = ({ [workspaceSlug, projectId, issueId, issueDetail] ); + useEffect(() => { + if (!createLabelForm) return; + + reset(); + }, [createLabelForm, reset]); + const isNotAllowed = userAuth.isGuest || userAuth.isViewer; return ( @@ -431,24 +437,25 @@ export const IssueDetailsSidebar: React.FC = ({ )} /> - + {!isNotAllowed && ( + + )} diff --git a/apps/app/components/modules/single-module-card.tsx b/apps/app/components/modules/single-module-card.tsx index 6bd59d14f..ed0d027b5 100644 --- a/apps/app/components/modules/single-module-card.tsx +++ b/apps/app/components/modules/single-module-card.tsx @@ -6,9 +6,10 @@ import { useRouter } from "next/router"; // components import { DeleteModuleModal } from "components/modules"; +// ui +import { AssigneesList, Avatar } from "components/ui"; // icons import { CalendarDaysIcon, TrashIcon } from "@heroicons/react/24/outline"; -import User from "public/user.png"; // helpers import { renderShortNumericDateFormat } from "helpers/date-time.helper"; // types @@ -21,10 +22,12 @@ type Props = { }; export const SingleModuleCard: React.FC = ({ module }) => { - const router = useRouter(); - const { workspaceSlug } = router.query; const [moduleDeleteModal, setModuleDeleteModal] = useState(false); const [selectedModuleForDelete, setSelectedModuleForDelete] = useState(); + + const router = useRouter(); + const { workspaceSlug } = router.query; + const handleDeleteModule = () => { if (!module) return; @@ -33,16 +36,7 @@ export const SingleModuleCard: React.FC = ({ module }) => { }; return ( -
-
- -
+ <> = ({ module }) => { setIsOpen={setModuleDeleteModal} data={selectedModuleForDelete} /> - - - {module.name} -
-
-
LEAD
-
- {module.lead ? ( - module.lead_detail?.avatar && module.lead_detail.avatar !== "" ? ( -
- {module.lead_detail.first_name} -
- ) : ( -
- {module.lead_detail?.first_name && module.lead_detail.first_name !== "" - ? module.lead_detail.first_name.charAt(0) - : module.lead_detail?.email.charAt(0)} -
- ) - ) : ( - "N/A" - )} +
- - -
+ + +
+ ); }; diff --git a/apps/app/components/states/single-state.tsx b/apps/app/components/states/single-state.tsx index ef558d302..d51684275 100644 --- a/apps/app/components/states/single-state.tsx +++ b/apps/app/components/states/single-state.tsx @@ -142,13 +142,16 @@ export const SingleState: React.FC = ({ }`} >
-
-
{addSpaceIfCamelCase(state.name)}
+
+
{addSpaceIfCamelCase(state.name)}
+

{state.description}

+
{index !== 0 && ( diff --git a/apps/app/components/ui/avatar/avatar.tsx b/apps/app/components/ui/avatar.tsx similarity index 96% rename from apps/app/components/ui/avatar/avatar.tsx rename to apps/app/components/ui/avatar.tsx index cb36d07b3..9d7e83700 100644 --- a/apps/app/components/ui/avatar/avatar.tsx +++ b/apps/app/components/ui/avatar.tsx @@ -13,7 +13,7 @@ import { IUser, IUserLite } from "types"; import { WORKSPACE_MEMBERS } from "constants/fetch-keys"; type AvatarProps = { - user: Partial | Partial | undefined; + user?: Partial | Partial | IUser | IUserLite | undefined | null; index?: number; }; diff --git a/apps/app/components/ui/avatar/index.ts b/apps/app/components/ui/avatar/index.ts deleted file mode 100644 index 90fdb226b..000000000 --- a/apps/app/components/ui/avatar/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./avatar"; diff --git a/apps/app/components/ui/index.ts b/apps/app/components/ui/index.ts index 1a16e2072..8311c0237 100644 --- a/apps/app/components/ui/index.ts +++ b/apps/app/components/ui/index.ts @@ -1,4 +1,3 @@ -// components export * from "./button"; export * from "./custom-listbox"; export * from "./custom-menu"; @@ -11,6 +10,6 @@ export * from "./outline-button"; export * from "./select"; export * from "./spinner"; export * from "./text-area"; -export * from "./tooltip"; export * from "./avatar"; export * from "./datepicker"; +export * from "./tooltip"; diff --git a/apps/app/constants/issue.ts b/apps/app/constants/issue.ts index 00bee0aa8..e37a8079d 100644 --- a/apps/app/constants/issue.ts +++ b/apps/app/constants/issue.ts @@ -5,6 +5,7 @@ export const GROUP_BY_OPTIONS: Array<{ name: string; key: NestedKeyOf | { name: "State", key: "state_detail.name" }, { name: "Priority", key: "priority" }, { name: "Created By", key: "created_by" }, + { name: "Assignee", key: "assignees" }, { name: "None", key: null }, ]; diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx index f5cd0f37e..b4f12ddfb 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx @@ -80,7 +80,7 @@ const StatesSettings: NextPage = (props) => {

States

-

Manage the state of this project.

+

Manage the states of this project.

{states && projectDetails ? ( From fcba3325899c67eef4b5e05cddeb2ba6bd481e37 Mon Sep 17 00:00:00 2001 From: pablohashescobar <118773738+pablohashescobar@users.noreply.github.com> Date: Tue, 14 Feb 2023 14:50:16 +0530 Subject: [PATCH 3/4] refactor: update django admin panel heading (#276) --- apiserver/templates/admin/base_site.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apiserver/templates/admin/base_site.html b/apiserver/templates/admin/base_site.html index 4fdb5e19b..fd1d89067 100644 --- a/apiserver/templates/admin/base_site.html +++ b/apiserver/templates/admin/base_site.html @@ -17,7 +17,7 @@ color: #FFFFFF; } -

{% trans 'plane Admin' %}

+

{% trans 'Plane Django Admin' %}

{% endblock %}{% block nav-global %}{% endblock %} From 6f0539f01da6b2752623cb33ae6b914427ccfeea Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Tue, 14 Feb 2023 20:05:32 +0530 Subject: [PATCH 4/4] feat: create label option in create issue modal (#281) --- .../components/account/email-code-form.tsx | 8 +- .../components/core/board-view/all-boards.tsx | 6 + .../core/board-view/single-board.tsx | 9 + .../core/board-view/single-issue.tsx | 29 +- .../components/core/issues-view-filter.tsx | 37 ++- apps/app/components/core/issues-view.tsx | 8 + .../core/sidebar/sidebar-progress-stats.tsx | 7 +- apps/app/components/issues/form.tsx | 18 +- apps/app/components/issues/select/label.tsx | 91 +----- .../components/labels/create-label-modal.tsx | 189 +++++++++++++ apps/app/components/labels/index.ts | 1 + .../modules/delete-module-modal.tsx | 4 - apps/app/components/modules/sidebar.tsx | 18 +- .../components/modules/single-module-card.tsx | 15 +- .../components/states/create-state-modal.tsx | 227 +++++++++++++++ .../states/create-update-state-modal.tsx | 263 ------------------ apps/app/components/states/index.ts | 2 +- apps/app/contexts/issue-view.context.tsx | 3 +- .../[projectId]/modules/[moduleId].tsx | 62 +---- .../index.tsx => invitations.tsx} | 61 ++-- 20 files changed, 580 insertions(+), 478 deletions(-) create mode 100644 apps/app/components/labels/create-label-modal.tsx create mode 100644 apps/app/components/states/create-state-modal.tsx delete mode 100644 apps/app/components/states/create-update-state-modal.tsx rename apps/app/pages/{invitations/index.tsx => invitations.tsx} (81%) diff --git a/apps/app/components/account/email-code-form.tsx b/apps/app/components/account/email-code-form.tsx index 98ab10cb7..003d515f4 100644 --- a/apps/app/components/account/email-code-form.tsx +++ b/apps/app/components/account/email-code-form.tsx @@ -114,15 +114,15 @@ export const EmailCodeForm = ({ onSuccess }: any) => { error={errors.token} placeholder="Enter code" /> - {/* { - console.log("Triggered"); handleSubmit(onSubmit); }} > Resend code - */} + */}
)}
diff --git a/apps/app/components/core/board-view/all-boards.tsx b/apps/app/components/core/board-view/all-boards.tsx index d4e995403..f5b03267c 100644 --- a/apps/app/components/core/board-view/all-boards.tsx +++ b/apps/app/components/core/board-view/all-boards.tsx @@ -11,9 +11,11 @@ type Props = { states: IState[] | undefined; members: IProjectMember[] | undefined; addIssueToState: (groupTitle: string, stateId: string | null) => void; + handleEditIssue: (issue: IIssue) => void; openIssuesListModal?: (() => void) | null; handleDeleteIssue: (issue: IIssue) => void; handleTrashBox: (isDragging: boolean) => void; + removeIssue: ((bridgeId: string) => void) | null; userAuth: UserAuth; }; @@ -23,9 +25,11 @@ export const AllBoards: React.FC = ({ states, members, addIssueToState, + handleEditIssue, openIssuesListModal, handleDeleteIssue, handleTrashBox, + removeIssue, userAuth, }) => { const { groupedByIssues, groupByProperty: selectedGroup, orderBy } = useIssueView(issues); @@ -57,11 +61,13 @@ export const AllBoards: React.FC = ({ groupedByIssues={groupedByIssues} selectedGroup={selectedGroup} members={members} + handleEditIssue={handleEditIssue} addIssueToState={() => addIssueToState(singleGroup, stateId)} handleDeleteIssue={handleDeleteIssue} openIssuesListModal={openIssuesListModal ?? null} orderBy={orderBy} handleTrashBox={handleTrashBox} + removeIssue={removeIssue} userAuth={userAuth} /> ); diff --git a/apps/app/components/core/board-view/single-board.tsx b/apps/app/components/core/board-view/single-board.tsx index e0e790da5..b9600a47c 100644 --- a/apps/app/components/core/board-view/single-board.tsx +++ b/apps/app/components/core/board-view/single-board.tsx @@ -25,11 +25,13 @@ type Props = { }; selectedGroup: NestedKeyOf | null; members: IProjectMember[] | undefined; + handleEditIssue: (issue: IIssue) => void; addIssueToState: () => void; handleDeleteIssue: (issue: IIssue) => void; openIssuesListModal?: (() => void) | null; orderBy: NestedKeyOf | "manual" | null; handleTrashBox: (isDragging: boolean) => void; + removeIssue: ((bridgeId: string) => void) | null; userAuth: UserAuth; }; @@ -40,11 +42,13 @@ export const SingleBoard: React.FC = ({ groupedByIssues, selectedGroup, members, + handleEditIssue, addIssueToState, handleDeleteIssue, openIssuesListModal, orderBy, handleTrashBox, + removeIssue, userAuth, }) => { // collapse/expand @@ -104,10 +108,15 @@ export const SingleBoard: React.FC = ({ snapshot={snapshot} type={type} issue={issue} + selectedGroup={selectedGroup} properties={properties} + editIssue={() => handleEditIssue(issue)} handleDeleteIssue={handleDeleteIssue} orderBy={orderBy} handleTrashBox={handleTrashBox} + removeIssue={() => { + removeIssue && removeIssue(issue.bridge); + }} userAuth={userAuth} /> )} diff --git a/apps/app/components/core/board-view/single-issue.tsx b/apps/app/components/core/board-view/single-issue.tsx index 945592788..a19c683e2 100644 --- a/apps/app/components/core/board-view/single-issue.tsx +++ b/apps/app/components/core/board-view/single-issue.tsx @@ -23,6 +23,8 @@ import { ViewPrioritySelect, ViewStateSelect, } from "components/issues/view-select"; +// ui +import { CustomMenu } from "components/ui"; // types import { CycleIssueResponse, @@ -41,7 +43,10 @@ type Props = { provided: DraggableProvided; snapshot: DraggableStateSnapshot; issue: IIssue; + selectedGroup: NestedKeyOf | null; properties: Properties; + editIssue: () => void; + removeIssue?: (() => void) | null; handleDeleteIssue: (issue: IIssue) => void; orderBy: NestedKeyOf | "manual" | null; handleTrashBox: (isDragging: boolean) => void; @@ -53,7 +58,10 @@ export const SingleBoardIssue: React.FC = ({ provided, snapshot, issue, + selectedGroup, properties, + editIssue, + removeIssue, handleDeleteIssue, orderBy, handleTrashBox, @@ -170,13 +178,26 @@ export const SingleBoardIssue: React.FC = ({
{!isNotAllowed && (
- + */} + {type && !isNotAllowed && ( + + Edit + {type !== "issue" && removeIssue && ( + + <>Remove from {type} + + )} + handleDeleteIssue(issue)}> + Delete permanently + + + )}
)} @@ -195,7 +216,7 @@ export const SingleBoardIssue: React.FC = ({
- {properties.priority && ( + {properties.priority && selectedGroup !== "priority" && ( = ({ position="left" /> )} - {properties.state && ( + {properties.state && selectedGroup !== "state_detail.name" && ( = ({ issues }) => {

Display Properties

- {Object.keys(properties).map((key) => ( - - ))} + {Object.keys(properties).map((key) => { + if ( + issueView === "kanban" && + ((groupByProperty === "state_detail.name" && key === "state") || + (groupByProperty === "priority" && key === "priority")) + ) + return; + + return ( + + ); + })}
diff --git a/apps/app/components/core/issues-view.tsx b/apps/app/components/core/issues-view.tsx index 2edb7f804..b3278ec3e 100644 --- a/apps/app/components/core/issues-view.tsx +++ b/apps/app/components/core/issues-view.tsx @@ -452,9 +452,17 @@ export const IssuesView: React.FC = ({ states={states} members={members} addIssueToState={addIssueToState} + handleEditIssue={handleEditIssue} openIssuesListModal={type !== "issue" ? openIssuesListModal : null} handleDeleteIssue={handleDeleteIssue} handleTrashBox={handleTrashBox} + removeIssue={ + type === "cycle" + ? removeIssueFromCycle + : type === "module" + ? removeIssueFromModule + : null + } userAuth={userAuth} /> )} diff --git a/apps/app/components/core/sidebar/sidebar-progress-stats.tsx b/apps/app/components/core/sidebar/sidebar-progress-stats.tsx index ea8e1e401..8fb073f54 100644 --- a/apps/app/components/core/sidebar/sidebar-progress-stats.tsx +++ b/apps/app/components/core/sidebar/sidebar-progress-stats.tsx @@ -10,6 +10,8 @@ import { Tab } from "@headlessui/react"; // services import issuesServices from "services/issues.service"; import projectService from "services/project.service"; +// hooks +import useLocalStorage from "hooks/use-local-storage"; // components import { SingleProgressStats } from "components/core"; // ui @@ -20,7 +22,6 @@ import User from "public/user.png"; import { IIssue, IIssueLabels } from "types"; // fetch-keys import { PROJECT_ISSUE_LABELS, PROJECT_MEMBERS } from "constants/fetch-keys"; -import useLocalStorage from "hooks/use-local-storage"; // types type Props = { groupedIssues: any; @@ -39,8 +40,10 @@ const stateGroupColours: { export const SidebarProgressStats: React.FC = ({ groupedIssues, issues }) => { const router = useRouter(); - const [tab, setTab] = useLocalStorage("tab", "Assignees"); const { workspaceSlug, projectId } = router.query; + + const [tab, setTab] = useLocalStorage("tab", "Assignees"); + const { data: issueLabels } = useSWR( workspaceSlug && projectId ? PROJECT_ISSUE_LABELS(projectId as string) : null, workspaceSlug && projectId diff --git a/apps/app/components/issues/form.tsx b/apps/app/components/issues/form.tsx index 5e034822a..3194481b6 100644 --- a/apps/app/components/issues/form.tsx +++ b/apps/app/components/issues/form.tsx @@ -16,8 +16,9 @@ import { IssueStateSelect, } from "components/issues/select"; import { CycleSelect as IssueCycleSelect } from "components/cycles/select"; -import { CreateUpdateStateModal } from "components/states"; +import { CreateStateModal } from "components/states"; import CreateUpdateCycleModal from "components/project/cycles/create-update-cycle-modal"; +import { CreateLabelModal } from "components/labels"; // ui import { Button, CustomDatePicker, CustomMenu, Input, Loader } from "components/ui"; // icons @@ -74,6 +75,7 @@ export const IssueForm: FC = ({ const [mostSimilarIssue, setMostSimilarIssue] = useState(); const [cycleModal, setCycleModal] = useState(false); const [stateModal, setStateModal] = useState(false); + const [labelModal, setLabelModal] = useState(false); const [parentIssueListModalOpen, setParentIssueListModalOpen] = useState(false); const router = useRouter(); @@ -121,7 +123,7 @@ export const IssueForm: FC = ({ <> {projectId && ( <> - setStateModal(false)} projectId={projectId} @@ -131,6 +133,11 @@ export const IssueForm: FC = ({ setIsOpen={setCycleModal} projectId={projectId} /> + setLabelModal(false)} + projectId={projectId} + /> )}
@@ -281,7 +288,12 @@ export const IssueForm: FC = ({ control={control} name="labels_list" render={({ field: { value, onChange } }) => ( - + )} />
diff --git a/apps/app/components/issues/select/label.tsx b/apps/app/components/issues/select/label.tsx index 2d4e5a179..f0a1d2d64 100644 --- a/apps/app/components/issues/select/label.tsx +++ b/apps/app/components/issues/select/label.tsx @@ -1,15 +1,13 @@ -import React, { useEffect, useState } from "react"; +import React, { useState } from "react"; import { useRouter } from "next/router"; import useSWR from "swr"; -// react-hook-form -import { useForm } from "react-hook-form"; // headless ui import { Combobox, Transition } from "@headlessui/react"; // icons -import { RectangleGroupIcon, TagIcon } from "@heroicons/react/24/outline"; +import { PlusIcon, RectangleGroupIcon, TagIcon } from "@heroicons/react/24/outline"; // services import issuesServices from "services/issues.service"; // types @@ -18,55 +16,26 @@ import type { IIssueLabels } from "types"; import { PROJECT_ISSUE_LABELS } from "constants/fetch-keys"; type Props = { + setIsOpen: React.Dispatch>; value: string[]; onChange: (value: string[]) => void; projectId: string; }; -const defaultValues: Partial = { - name: "", -}; - -export const IssueLabelSelect: React.FC = ({ value, onChange, projectId }) => { +export const IssueLabelSelect: React.FC = ({ setIsOpen, value, onChange, projectId }) => { // states const [query, setQuery] = useState(""); const router = useRouter(); const { workspaceSlug } = router.query; - const [isOpen, setIsOpen] = useState(false); - - const { data: issueLabels, mutate: issueLabelsMutate } = useSWR( + const { data: issueLabels } = useSWR( projectId ? PROJECT_ISSUE_LABELS(projectId) : null, workspaceSlug && projectId ? () => issuesServices.getIssueLabels(workspaceSlug as string, projectId) : null ); - const onSubmit = async (data: IIssueLabels) => { - if (!projectId || !workspaceSlug || isSubmitting) return; - await issuesServices - .createIssueLabel(workspaceSlug as string, projectId as string, data) - .then((response) => { - issueLabelsMutate((prevData) => [...(prevData ?? []), response], false); - setIsOpen(false); - reset(defaultValues); - }) - .catch((error) => { - console.log(error); - }); - }; - - const { - formState: { isSubmitting }, - setFocus, - reset, - } = useForm({ defaultValues }); - - useEffect(() => { - isOpen && setFocus("name"); - }, [isOpen, setFocus]); - const filteredOptions = query === "" ? issueLabels @@ -175,48 +144,14 @@ export const IssueLabelSelect: React.FC = ({ value, onChange, projectId } ) : (

Loading...

)} - {/*
- {isOpen ? ( -
- - - -
- ) : ( - - )} -
*/} +
diff --git a/apps/app/components/labels/create-label-modal.tsx b/apps/app/components/labels/create-label-modal.tsx new file mode 100644 index 000000000..89c286012 --- /dev/null +++ b/apps/app/components/labels/create-label-modal.tsx @@ -0,0 +1,189 @@ +import React, { useEffect } from "react"; + +import { useRouter } from "next/router"; + +import { mutate } from "swr"; + +// react-hook-form +import { Controller, useForm } from "react-hook-form"; +// react-color +import { TwitterPicker } from "react-color"; +// headless ui +import { Dialog, Popover, Transition } from "@headlessui/react"; +// services +import issuesService from "services/issues.service"; +// ui +import { Button, Input } from "components/ui"; +// icons +import { ChevronDownIcon } from "@heroicons/react/24/outline"; +// types +import type { IIssueLabels, IState } from "types"; +// constants +import { PROJECT_ISSUE_LABELS } from "constants/fetch-keys"; + +// types +type Props = { + isOpen: boolean; + projectId: string; + handleClose: () => void; +}; + +const defaultValues: Partial = { + name: "", + color: "#000000", +}; + +export const CreateLabelModal: React.FC = ({ isOpen, projectId, handleClose }) => { + const router = useRouter(); + const { workspaceSlug } = router.query; + + const { + register, + formState: { errors, isSubmitting }, + handleSubmit, + watch, + control, + reset, + setError, + } = useForm({ + defaultValues, + }); + + const onClose = () => { + handleClose(); + reset(defaultValues); + }; + + const onSubmit = async (formData: IIssueLabels) => { + if (!workspaceSlug) return; + + await issuesService + .createIssueLabel(workspaceSlug as string, projectId as string, formData) + .then((res) => { + mutate( + PROJECT_ISSUE_LABELS(projectId), + (prevData) => [res, ...(prevData ?? [])], + false + ); + onClose(); + }) + .catch((error) => { + console.log(error); + }); + }; + + return ( + + + +
+ + +
+
+ + + +
+ + Create Label + +
+ + {({ open }) => ( + <> + + Color + {watch("color") && watch("color") !== "" && ( + + )} + + + + + ( + onChange(value.hex)} + /> + )} + /> + + + + )} + + +
+
+
+ + +
+ +
+
+
+
+
+
+ ); +}; diff --git a/apps/app/components/labels/index.ts b/apps/app/components/labels/index.ts index d407cd074..db02d29f0 100644 --- a/apps/app/components/labels/index.ts +++ b/apps/app/components/labels/index.ts @@ -1,3 +1,4 @@ +export * from "./create-label-modal"; export * from "./create-update-label-inline"; export * from "./labels-list-modal"; export * from "./single-label-group"; diff --git a/apps/app/components/modules/delete-module-modal.tsx b/apps/app/components/modules/delete-module-modal.tsx index 317f49a68..05ed67089 100644 --- a/apps/app/components/modules/delete-module-modal.tsx +++ b/apps/app/components/modules/delete-module-modal.tsx @@ -65,10 +65,6 @@ export const DeleteModuleModal: React.FC = ({ isOpen, setIsOpen, data }) }); }; - useEffect(() => { - data && setIsOpen(true); - }, [data, setIsOpen]); - return ( void; }; -export const ModuleDetailsSidebar: React.FC = ({ - issues, - module, - isOpen, - moduleIssues, - handleDeleteModule, -}) => { +export const ModuleDetailsSidebar: React.FC = ({ issues, module, isOpen, moduleIssues }) => { + const [moduleDeleteModal, setModuleDeleteModal] = useState(false); const [moduleLinkModal, setModuleLinkModal] = useState(false); const router = useRouter(); @@ -127,6 +122,11 @@ export const ModuleDetailsSidebar: React.FC = ({ handleClose={() => setModuleLinkModal(false)} module={module} /> +
= ({ diff --git a/apps/app/components/modules/single-module-card.tsx b/apps/app/components/modules/single-module-card.tsx index ed0d027b5..a53fc4353 100644 --- a/apps/app/components/modules/single-module-card.tsx +++ b/apps/app/components/modules/single-module-card.tsx @@ -1,7 +1,6 @@ import React, { useState } from "react"; import Link from "next/link"; -import Image from "next/image"; import { useRouter } from "next/router"; // components @@ -13,7 +12,7 @@ import { CalendarDaysIcon, TrashIcon } from "@heroicons/react/24/outline"; // helpers import { renderShortNumericDateFormat } from "helpers/date-time.helper"; // types -import { IModule, SelectModuleType } from "types"; +import { IModule } from "types"; // common import { MODULE_STATUS } from "constants/module"; @@ -23,7 +22,6 @@ type Props = { export const SingleModuleCard: React.FC = ({ module }) => { const [moduleDeleteModal, setModuleDeleteModal] = useState(false); - const [selectedModuleForDelete, setSelectedModuleForDelete] = useState(); const router = useRouter(); const { workspaceSlug } = router.query; @@ -31,23 +29,18 @@ export const SingleModuleCard: React.FC = ({ module }) => { const handleDeleteModule = () => { if (!module) return; - setSelectedModuleForDelete({ ...module, actionType: "delete" }); setModuleDeleteModal(true); }; return ( <>
-
+