From 4f4f3ebbdec9908f4798354d905c25254a2731ad Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Sun, 5 Mar 2023 23:24:50 +0530 Subject: [PATCH] chore: updated sidebar selects --- .../core/board-view/single-issue.tsx | 2 +- .../core/list-view/single-issue.tsx | 2 +- .../components/issues/my-issues-list-item.tsx | 4 +- .../issues/sidebar-select/assignee.tsx | 157 +++++---------- .../issues/sidebar-select/cycle.tsx | 27 +-- .../issues/sidebar-select/module.tsx | 27 +-- .../issues/sidebar-select/priority.tsx | 65 +++--- .../issues/sidebar-select/state.tsx | 98 ++++----- apps/app/components/issues/sidebar.tsx | 36 +++- .../issues/view-select/assignee.tsx | 78 +------ .../components/issues/view-select/state.tsx | 66 +++--- .../modules/sidebar-select/select-lead.tsx | 190 ++++++------------ .../modules/sidebar-select/select-members.tsx | 153 +++++--------- apps/app/components/modules/sidebar.tsx | 42 ++-- .../project/send-project-invitation-modal.tsx | 105 +++------- apps/app/components/ui/avatar.tsx | 2 +- apps/app/components/ui/context-menu.tsx | 14 +- .../components/ui/custom-search-select.tsx | 30 +-- apps/app/components/ui/datepicker.tsx | 8 +- 19 files changed, 389 insertions(+), 717 deletions(-) diff --git a/apps/app/components/core/board-view/single-issue.tsx b/apps/app/components/core/board-view/single-issue.tsx index 2d2c34626..1239da0d4 100644 --- a/apps/app/components/core/board-view/single-issue.tsx +++ b/apps/app/components/core/board-view/single-issue.tsx @@ -294,7 +294,7 @@ export const SingleBoardIssue: React.FC = ({ /> )} {properties.sub_issue_count && ( -
+
{issue.sub_issues_count} {issue.sub_issues_count === 1 ? "sub-issue" : "sub-issues"}
)} diff --git a/apps/app/components/core/list-view/single-issue.tsx b/apps/app/components/core/list-view/single-issue.tsx index 134fffa1c..8e76237e9 100644 --- a/apps/app/components/core/list-view/single-issue.tsx +++ b/apps/app/components/core/list-view/single-issue.tsx @@ -236,7 +236,7 @@ export const SingleListIssue: React.FC = ({ /> )} {properties.sub_issue_count && ( -
+
{issue.sub_issues_count} {issue.sub_issues_count === 1 ? "sub-issue" : "sub-issues"}
)} diff --git a/apps/app/components/issues/my-issues-list-item.tsx b/apps/app/components/issues/my-issues-list-item.tsx index 63a8ad5e8..740da34ba 100644 --- a/apps/app/components/issues/my-issues-list-item.tsx +++ b/apps/app/components/issues/my-issues-list-item.tsx @@ -105,7 +105,7 @@ export const MyIssuesListItem: React.FC = ({ )} - + {issue.name} @@ -135,7 +135,7 @@ export const MyIssuesListItem: React.FC = ({ /> )} {properties.sub_issue_count && ( -
+
{issue?.sub_issues_count} {issue?.sub_issues_count === 1 ? "sub-issue" : "sub-issues"}
)} diff --git a/apps/app/components/issues/sidebar-select/assignee.tsx b/apps/app/components/issues/sidebar-select/assignee.tsx index 2d8088059..0d45143a3 100644 --- a/apps/app/components/issues/sidebar-select/assignee.tsx +++ b/apps/app/components/issues/sidebar-select/assignee.tsx @@ -1,41 +1,57 @@ import React from "react"; -import Image from "next/image"; import { useRouter } from "next/router"; import useSWR from "swr"; -// react-hook-form -import { Control, Controller } from "react-hook-form"; -// headless ui -import { Listbox, Transition } from "@headlessui/react"; // services -import { UserGroupIcon } from "@heroicons/react/24/outline"; -import workspaceService from "services/workspace.service"; -// hooks +import projectService from "services/project.service"; // ui -import { AssigneesList } from "components/ui/avatar"; -import { Spinner } from "components/ui"; +import { CustomSearchSelect } from "components/ui"; +import { AssigneesList, Avatar } from "components/ui/avatar"; +// icons +import { UserGroupIcon } from "@heroicons/react/24/outline"; // types -import { IIssue, UserAuth } from "types"; -// constants -import { WORKSPACE_MEMBERS } from "constants/fetch-keys"; +import { UserAuth } from "types"; +// fetch-keys +import { PROJECT_MEMBERS } from "constants/fetch-keys"; type Props = { - control: Control; - submitChanges: (formData: Partial) => void; + value: string[]; + onChange: (val: string[]) => void; userAuth: UserAuth; }; -export const SidebarAssigneeSelect: React.FC = ({ control, submitChanges, userAuth }) => { +export const SidebarAssigneeSelect: React.FC = ({ value, onChange, userAuth }) => { const router = useRouter(); - const { workspaceSlug } = router.query; + const { workspaceSlug, projectId } = router.query; - const { data: people } = useSWR( - workspaceSlug ? WORKSPACE_MEMBERS(workspaceSlug as string) : null, - workspaceSlug ? () => workspaceService.workspaceMembers(workspaceSlug as string) : null + const { data: members } = useSWR( + workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, + workspaceSlug && projectId + ? () => projectService.projectMembers(workspaceSlug as string, projectId as string) + : null ); + const options = + members?.map((member) => ({ + value: member.member.id, + query: + (member.member.first_name && member.member.first_name !== "" + ? member.member.first_name + : member.member.email) + + " " + + member.member.last_name ?? "", + content: ( +
+ + {member.member.first_name && member.member.first_name !== "" + ? member.member.first_name + : member.member.email} +
+ ), + })) ?? []; + const isNotAllowed = userAuth.isGuest || userAuth.isViewer; return ( @@ -45,93 +61,24 @@ export const SidebarAssigneeSelect: React.FC = ({ control, submitChanges,

Assignees

- ( - { - submitChanges({ assignees_list: value }); - }} - className="flex-shrink-0" - disabled={isNotAllowed} - > - {({ open }) => ( -
- -
- {value && Array.isArray(value) ? ( - - ) : null} -
-
- - - -
- {people ? ( - people.length > 0 ? ( - people.map((option) => ( - - `${active || selected ? "bg-indigo-50" : ""} ${ - selected ? "font-medium" : "" - } flex cursor-pointer select-none items-center gap-2 truncate p-2 text-gray-900` - } - value={option.member.id} - > - {option.member.avatar && option.member.avatar !== "" ? ( -
- avatar -
- ) : ( -
- {option.member.first_name && option.member.first_name !== "" - ? option.member.first_name.charAt(0) - : option.member.email.charAt(0)} -
- )} - {option.member.first_name && option.member.first_name !== "" - ? option.member.first_name - : option.member.email} -
- )) - ) : ( -
No assignees found
- ) - ) : ( - - )} -
-
-
+ + {value && value.length > 0 && Array.isArray(value) ? ( +
+ + {value.length} Assignees
+ ) : ( + "No assignees" )} - - )} +
+ } + options={options} + onChange={onChange} + multiple + disabled={isNotAllowed} />
diff --git a/apps/app/components/issues/sidebar-select/cycle.tsx b/apps/app/components/issues/sidebar-select/cycle.tsx index 127c78eba..2d1251454 100644 --- a/apps/app/components/issues/sidebar-select/cycle.tsx +++ b/apps/app/components/issues/sidebar-select/cycle.tsx @@ -65,26 +65,21 @@ export const SidebarCycleSelect: React.FC = ({
- - {issueCycle ? issueCycle.cycle_detail.name : "None"} - - + {issueCycle ? issueCycle.cycle_detail.name : "None"} + } value={issueCycle?.cycle_detail.id} onChange={(value: any) => { - value === null + !value ? removeIssueFromCycle(issueCycle?.id ?? "", issueCycle?.cycle ?? "") : handleCycleChange(cycles?.find((c) => c.id === value) as ICycle); }} + width="w-full" disabled={isNotAllowed} > {cycles ? ( @@ -97,11 +92,7 @@ export const SidebarCycleSelect: React.FC = ({ ))} - - - None - - + 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 90661a0df..977ae7649 100644 --- a/apps/app/components/issues/sidebar-select/module.tsx +++ b/apps/app/components/issues/sidebar-select/module.tsx @@ -64,26 +64,21 @@ export const SidebarModuleSelect: React.FC = ({
m.id === issueModule?.module)?.name ?? "None"} + - - {modules?.find((m) => m.id === issueModule?.module)?.name ?? "None"} - - + {modules?.find((m) => m.id === issueModule?.module)?.name ?? "None"} + } value={issueModule?.module_detail?.id} onChange={(value: any) => { - value === null + !value ? removeIssueFromModule(issueModule?.id ?? "", issueModule?.module ?? "") : handleModuleChange(modules?.find((m) => m.id === value) as IModule); }} + width="w-full" disabled={isNotAllowed} > {modules ? ( @@ -96,11 +91,7 @@ export const SidebarModuleSelect: React.FC = ({ ))} - - - None - - + None ) : (
No modules found
diff --git a/apps/app/components/issues/sidebar-select/priority.tsx b/apps/app/components/issues/sidebar-select/priority.tsx index 7583f16f4..b3464a106 100644 --- a/apps/app/components/issues/sidebar-select/priority.tsx +++ b/apps/app/components/issues/sidebar-select/priority.tsx @@ -1,24 +1,22 @@ import React from "react"; -// react-hook-form -import { Control, Controller } from "react-hook-form"; // ui import { CustomSelect } from "components/ui"; // icons import { ChartBarIcon } from "@heroicons/react/24/outline"; import { getPriorityIcon } from "components/icons/priority-icon"; // types -import { IIssue, UserAuth } from "types"; +import { UserAuth } from "types"; // constants import { PRIORITIES } from "constants/project"; type Props = { - control: Control; - submitChanges: (formData: Partial) => void; + value: string | null; + onChange: (val: string) => void; userAuth: UserAuth; }; -export const SidebarPrioritySelect: React.FC = ({ control, submitChanges, userAuth }) => { +export const SidebarPrioritySelect: React.FC = ({ value, onChange, userAuth }) => { const isNotAllowed = userAuth.isGuest || userAuth.isViewer; return ( @@ -28,38 +26,31 @@ export const SidebarPrioritySelect: React.FC = ({ control, submitChanges,

Priority

- ( - - {getPriorityIcon(value && value !== "" ? value ?? "" : "None", "text-sm")} - {value && value !== "" ? value : "None"} - - } - value={value} - onChange={(value: any) => { - submitChanges({ priority: value }); - }} - disabled={isNotAllowed} + - {PRIORITIES.map((option) => ( - - <> - {getPriorityIcon(option, "text-sm")} - {option ?? "None"} - - - ))} - - )} - /> + {getPriorityIcon(value && value !== "" ? value ?? "" : "None", "text-sm")} + {value && value !== "" ? value : "None"} + + } + value={value} + onChange={onChange} + width="w-full" + disabled={isNotAllowed} + > + {PRIORITIES.map((option) => ( + + <> + {getPriorityIcon(option, "text-sm")} + {option ?? "None"} + + + ))} +
); diff --git a/apps/app/components/issues/sidebar-select/state.tsx b/apps/app/components/issues/sidebar-select/state.tsx index 0ed3a04bb..13ecd3c62 100644 --- a/apps/app/components/issues/sidebar-select/state.tsx +++ b/apps/app/components/issues/sidebar-select/state.tsx @@ -4,28 +4,28 @@ import { useRouter } from "next/router"; import useSWR from "swr"; -// react-hook-form -import { Control, Controller } from "react-hook-form"; // services import stateService from "services/state.service"; // ui import { Spinner, CustomSelect } from "components/ui"; // icons import { Squares2X2Icon } from "@heroicons/react/24/outline"; +import { getStateGroupIcon } from "components/icons"; // helpers import { getStatesList } from "helpers/state.helper"; +import { addSpaceIfCamelCase } from "helpers/string.helper"; // types -import { IIssue, UserAuth } from "types"; +import { UserAuth } from "types"; // constants import { STATE_LIST } from "constants/fetch-keys"; type Props = { - control: Control; - submitChanges: (formData: Partial) => void; + value: string; + onChange: (val: string) => void; userAuth: UserAuth; }; -export const SidebarStateSelect: React.FC = ({ control, submitChanges, userAuth }) => { +export const SidebarStateSelect: React.FC = ({ value, onChange, userAuth }) => { const router = useRouter(); const { workspaceSlug, projectId } = router.query; @@ -37,6 +37,8 @@ export const SidebarStateSelect: React.FC = ({ control, submitChanges, us ); const states = getStatesList(stateGroups ?? {}); + const selectedState = states?.find((s) => s.id === value); + const isNotAllowed = userAuth.isGuest || userAuth.isViewer; return ( @@ -46,60 +48,40 @@ export const SidebarStateSelect: React.FC = ({ control, submitChanges, us

State

- ( - - {value ? ( - <> - option.id === value)?.color, - }} - /> - {states?.find((option) => option.id === value)?.name} - - ) : ( - "None" - )} - - } - value={value} - onChange={(value: any) => { - submitChanges({ state: value }); - }} - disabled={isNotAllowed} - > - {states ? ( - states.length > 0 ? ( - states.map((option) => ( - - <> - {option.color && ( - - )} - {option.name} - - - )) - ) : ( -
No states found
- ) - ) : ( - + + {getStateGroupIcon( + selectedState?.group ?? "backlog", + "16", + "16", + selectedState?.color ?? "" )} - + {addSpaceIfCamelCase(selectedState?.name ?? "")} +
+ } + value={value} + onChange={onChange} + width="w-full" + disabled={isNotAllowed} + > + {states ? ( + states.length > 0 ? ( + states.map((state) => ( + + <> + {getStateGroupIcon(state.group, "16", "16", state.color)} + {state.name} + + + )) + ) : ( +
No states found
+ ) + ) : ( + )} - /> + ); diff --git a/apps/app/components/issues/sidebar.tsx b/apps/app/components/issues/sidebar.tsx index 9158b7738..5632dc015 100644 --- a/apps/app/components/issues/sidebar.tsx +++ b/apps/app/components/issues/sidebar.tsx @@ -243,20 +243,38 @@ export const IssueDetailsSidebar: React.FC = ({
- ( + submitChanges({ state: val })} + userAuth={userAuth} + /> + )} /> - ( + submitChanges({ assignees_list: val })} + userAuth={userAuth} + /> + )} /> - ( + submitChanges({ priority: val })} + userAuth={userAuth} + /> + )} />
diff --git a/apps/app/components/issues/view-select/assignee.tsx b/apps/app/components/issues/view-select/assignee.tsx index 2ab96ab08..6e9c900fd 100644 --- a/apps/app/components/issues/view-select/assignee.tsx +++ b/apps/app/components/issues/view-select/assignee.tsx @@ -4,17 +4,16 @@ import { useRouter } from "next/router"; import useSWR from "swr"; -// headless ui -import { Listbox, Transition } from "@headlessui/react"; // services import projectService from "services/project.service"; // ui import { AssigneesList, Avatar, CustomSearchSelect, Tooltip } from "components/ui"; +// icons +import { UserGroupIcon } from "@heroicons/react/24/outline"; // types import { IIssue } from "types"; // fetch-keys import { PROJECT_MEMBERS } from "constants/fetch-keys"; -import { UserGroupIcon } from "@heroicons/react/24/outline"; type Props = { issue: IIssue; @@ -112,78 +111,5 @@ export const ViewAssigneeSelect: React.FC = ({ position={position} disabled={isNotAllowed} /> - // { - // const newData = issue.assignees ?? []; - - // if (newData.includes(data)) newData.splice(newData.indexOf(data), 1); - // else newData.push(data); - - // partialUpdateIssue({ assignees_list: newData }); - // }} - // className={`group ${!selfPositioned ? "relative" : ""} flex-shrink-0`} - // disabled={isNotAllowed} - // > - // {({ open }) => ( - //
- // - // 0 - // ? issue.assignee_details - // .map((assignee) => - // assignee?.first_name !== "" ? assignee?.first_name : assignee?.email - // ) - // .join(", ") - // : "No Assignee" - // } - // > - //
- // - //
- //
- //
- - // - // - // {members?.map((member) => ( - // - // `flex cursor-pointer select-none items-center gap-x-1 whitespace-nowrap p-2 ${ - // active ? "bg-indigo-50" : "" - // } ${ - // selected || issue.assignees?.includes(member.member.id) - // ? "bg-indigo-50 font-medium" - // : "font-normal" - // }` - // } - // value={member.member.id} - // > - // - // {member.member.first_name && member.member.first_name !== "" - // ? member.member.first_name - // : member.member.email} - // - // ))} - // - // - //
- // )} - //
); }; diff --git a/apps/app/components/issues/view-select/state.tsx b/apps/app/components/issues/view-select/state.tsx index b7e10847c..b76a3c237 100644 --- a/apps/app/components/issues/view-select/state.tsx +++ b/apps/app/components/issues/view-select/state.tsx @@ -5,7 +5,9 @@ import useSWR from "swr"; // services import stateService from "services/state.service"; // ui -import { CustomSelect, Tooltip } from "components/ui"; +import { CustomSearchSelect, Tooltip } from "components/ui"; +// icons +import { getStateGroupIcon } from "components/icons"; // helpers import { addSpaceIfCamelCase } from "helpers/string.helper"; import { getStatesList } from "helpers/state.helper"; @@ -13,7 +15,6 @@ import { getStatesList } from "helpers/state.helper"; import { IIssue } from "types"; // fetch-keys import { STATE_LIST } from "constants/fetch-keys"; -import { getStateGroupIcon } from "components/icons"; type Props = { issue: IIssue; @@ -41,42 +42,39 @@ export const ViewStateSelect: React.FC = ({ ); const states = getStatesList(stateGroups ?? {}); - const currentState = states?.find((s) => s.id === issue.state); + const options = states?.map((state) => ({ + value: state.id, + query: state.name, + content: ( +
+ {getStateGroupIcon(state.group, "16", "16", state.color)} + {state.name} +
+ ), + })); + + const selectedOption = states?.find((s) => s.id === issue.state); return ( - - {getStateGroupIcon( - currentState?.group ?? "backlog", - "16", - "16", - currentState?.color ?? "" - )} - - {addSpaceIfCamelCase(currentState?.name ?? "")} - - - } + partialUpdateIssue({ state: data })} - maxHeight="md" - noChevron - disabled={isNotAllowed} + options={options} + label={ + +
+ {selectedOption && + getStateGroupIcon(selectedOption.group, "16", "16", selectedOption.color)} + {selectedOption?.name ?? "State"} +
+
+ } position={position} - selfPositioned={selfPositioned} - > - {states?.map((state) => ( - - <> - {getStateGroupIcon(state.group, "16", "16", state.color)} - {addSpaceIfCamelCase(state.name)} - - - ))} -
+ disabled={isNotAllowed} + noChevron + /> ); }; diff --git a/apps/app/components/modules/sidebar-select/select-lead.tsx b/apps/app/components/modules/sidebar-select/select-lead.tsx index 84f230692..a04354442 100644 --- a/apps/app/components/modules/sidebar-select/select-lead.tsx +++ b/apps/app/components/modules/sidebar-select/select-lead.tsx @@ -5,35 +5,53 @@ import { useRouter } from "next/router"; import useSWR from "swr"; -// react-hook-form -import { Control, Controller } from "react-hook-form"; -// headless ui -import { Listbox, Transition } from "@headlessui/react"; // services -import workspaceService from "services/workspace.service"; +import projectService from "services/project.service"; +// ui +import { Avatar, CustomSearchSelect } from "components/ui"; // icons import { UserIcon } from "@heroicons/react/24/outline"; import User from "public/user.png"; -// types -import { IModule, IUserLite } from "types"; // fetch-keys -import { WORKSPACE_MEMBERS } from "constants/fetch-keys"; +import { PROJECT_MEMBERS } from "constants/fetch-keys"; type Props = { - control: Control, any>; - submitChanges: (formData: Partial) => void; - lead: IUserLite | null; + value: string | null | undefined; + onChange: (val: string) => void; }; -export const SidebarLeadSelect: React.FC = ({ control, submitChanges, lead }) => { +export const SidebarLeadSelect: React.FC = ({ value, onChange }) => { const router = useRouter(); - const { workspaceSlug } = router.query; + const { workspaceSlug, projectId } = router.query; - const { data: people } = useSWR( - workspaceSlug ? WORKSPACE_MEMBERS(workspaceSlug as string) : null, - workspaceSlug ? () => workspaceService.workspaceMembers(workspaceSlug as string) : null + const { data: members } = useSWR( + workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, + workspaceSlug && projectId + ? () => projectService.projectMembers(workspaceSlug as string, projectId as string) + : null ); + const options = + members?.map((member) => ({ + value: member.member.id, + query: + (member.member.first_name && member.member.first_name !== "" + ? member.member.first_name + : member.member.email) + + " " + + member.member.last_name ?? "", + content: ( +
+ + {member.member.first_name && member.member.first_name !== "" + ? member.member.first_name + : member.member.email} +
+ ), + })) ?? []; + + const selectedOption = members?.find((m) => m.member.id === value)?.member; + return (
@@ -41,124 +59,32 @@ export const SidebarLeadSelect: React.FC = ({ control, submitChanges, lea

Lead

- ( - { - submitChanges({ lead: value }); - }} - className="flex-shrink-0" - > - {({ open }) => ( -
- - -
- {lead ? ( - lead.avatar && lead.avatar !== "" ? ( -
- {lead?.first_name} -
- ) : ( -
- {lead?.first_name && lead.first_name !== "" - ? lead.first_name.charAt(0) - : lead?.email.charAt(0)} -
- ) - ) : ( -
- No user -
- )} - {lead - ? lead?.first_name && lead.first_name !== "" - ? lead?.first_name - : lead?.email - : "N/A"} -
-
-
- - - -
- {people ? ( - people.length > 0 ? ( - people.map((option) => ( - - `${ - active || selected ? "bg-indigo-50" : "" - } flex cursor-pointer select-none items-center gap-2 truncate p-2 text-gray-900` - } - value={option.member.id} - > - {option.member.avatar && option.member.avatar !== "" ? ( -
- avatar -
- ) : ( -
- {option.member.first_name && option.member.first_name !== "" - ? option.member.first_name.charAt(0) - : option.member.email.charAt(0)} -
- )} - {option.member.first_name && option.member.first_name !== "" - ? option.member.first_name - : option.member.email} -
- )) - ) : ( -
No members found
- ) - ) : ( -

Loading...

- )} -
-
-
+ + {selectedOption ? ( + + ) : ( +
+ No user
)} - - )} + {selectedOption + ? selectedOption?.first_name && selectedOption.first_name !== "" + ? selectedOption?.first_name + : selectedOption?.email + : "N/A"} +
+ } + options={options} + onChange={onChange} />
diff --git a/apps/app/components/modules/sidebar-select/select-members.tsx b/apps/app/components/modules/sidebar-select/select-members.tsx index d99dee135..22efffa68 100644 --- a/apps/app/components/modules/sidebar-select/select-members.tsx +++ b/apps/app/components/modules/sidebar-select/select-members.tsx @@ -1,37 +1,53 @@ import React from "react"; -import Image from "next/image"; import { useRouter } from "next/router"; import useSWR from "swr"; -import { Control, Controller } from "react-hook-form"; // services -import { Listbox, Transition } from "@headlessui/react"; -import { UserGroupIcon } from "@heroicons/react/24/outline"; -import workspaceService from "services/workspace.service"; -// headless ui +import projectService from "services/project.service"; // ui -import { AssigneesList } from "components/ui"; -// types -import { IModule } from "types"; -// constants -import { WORKSPACE_MEMBERS } from "constants/fetch-keys"; +import { AssigneesList, Avatar, CustomSearchSelect } from "components/ui"; +// icons +import { UserGroupIcon } from "@heroicons/react/24/outline"; +// fetch-keys +import { PROJECT_MEMBERS } from "constants/fetch-keys"; type Props = { - control: Control, any>; - submitChanges: (formData: Partial) => void; + value: string[] | undefined; + onChange: (val: string[]) => void; }; -export const SidebarMembersSelect: React.FC = ({ control, submitChanges }) => { +export const SidebarMembersSelect: React.FC = ({ value, onChange }) => { const router = useRouter(); - const { workspaceSlug } = router.query; + const { workspaceSlug, projectId } = router.query; - const { data: people } = useSWR( - workspaceSlug ? WORKSPACE_MEMBERS(workspaceSlug as string) : null, - workspaceSlug ? () => workspaceService.workspaceMembers(workspaceSlug as string) : null + const { data: members } = useSWR( + workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, + workspaceSlug && projectId + ? () => projectService.projectMembers(workspaceSlug as string, projectId as string) + : null ); + const options = + members?.map((member) => ({ + value: member.member.id, + query: + (member.member.first_name && member.member.first_name !== "" + ? member.member.first_name + : member.member.email) + + " " + + member.member.last_name ?? "", + content: ( +
+ + {member.member.first_name && member.member.first_name !== "" + ? member.member.first_name + : member.member.email} +
+ ), + })) ?? []; + return (
@@ -39,94 +55,23 @@ export const SidebarMembersSelect: React.FC = ({ control, submitChanges }

Members

- ( - { - submitChanges({ members_list: value }); - }} - className="flex-shrink-0" - > - {({ open }) => ( -
- - -
- {value && Array.isArray(value) ? ( - - ) : null} -
-
-
- - - -
- {people ? ( - people.length > 0 ? ( - people.map((option) => ( - - `${ - active || selected ? "bg-indigo-50" : "" - } flex cursor-pointer select-none items-center gap-2 truncate p-2 text-gray-900` - } - value={option.member.id} - > - {option.member.avatar && option.member.avatar !== "" ? ( -
- avatar -
- ) : ( -
- {option.member.first_name && option.member.first_name !== "" - ? option.member.first_name.charAt(0) - : option.member.email.charAt(0)} -
- )} - {option.member.first_name && option.member.first_name !== "" - ? option.member.first_name - : option.member.email} -
- )) - ) : ( -
No members found
- ) - ) : ( -

Loading...

- )} -
-
-
+ + {value && value.length > 0 && Array.isArray(value) ? ( +
+ + {value.length} Assignees
+ ) : ( + "No members" )} - - )} +
+ } + options={options} + onChange={onChange} + multiple />
diff --git a/apps/app/components/modules/sidebar.tsx b/apps/app/components/modules/sidebar.tsx index 151526a50..edf211827 100644 --- a/apps/app/components/modules/sidebar.tsx +++ b/apps/app/components/modules/sidebar.tsx @@ -1,6 +1,5 @@ import React, { useEffect, useState } from "react"; -import Link from "next/link"; import { useRouter } from "next/router"; import { mutate } from "swr"; @@ -19,7 +18,6 @@ import { import { Popover, Transition } from "@headlessui/react"; import DatePicker from "react-datepicker"; - // services import modulesService from "services/modules.service"; // hooks @@ -184,7 +182,7 @@ export const ModuleDetailsSidebar: React.FC = ({ > {module ? ( <> -
+
= ({ {watch("status")} @@ -213,14 +211,14 @@ export const ModuleDetailsSidebar: React.FC = ({ )} />
-
- +
+ {({ open }) => ( <> - + {renderShortNumericDateFormat(`${module?.start_date}`) ? renderShortNumericDateFormat(`${module?.start_date}`) @@ -256,7 +254,7 @@ export const ModuleDetailsSidebar: React.FC = ({ )} - + {({ open }) => ( <> = ({
- ( + { + submitChanges({ lead: val }); + }} + /> + )} + /> + ( + { + submitChanges({ members_list: val }); + }} + /> + )} /> -
@@ -363,7 +379,7 @@ export const ModuleDetailsSidebar: React.FC = ({
-
+
{isStartValid && isEndValid ? ( = ({ isOpen, setIsOpen, member leaveFrom="opacity-100 translate-y-0 sm:scale-100" leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" > - +
@@ -148,77 +147,36 @@ const SendProjectInvitationModal: React.FC = ({ isOpen, setIsOpen, member name="user_id" rules={{ required: "Please select a member" }} render={({ field: { value, onChange } }) => ( - { - onChange(data.id); - setValue("member_id", data.id); - setValue("email", data.email); - }} - > - {({ open }) => ( - <> - - Email - -
- - - {value && value !== "" - ? people?.find((p) => p.member.id === value)?.member.email - : "Select email"} - - - - + label={ +
+ {value && value !== "" + ? people?.find((p) => p.member.id === value)?.member.email + : "Select email"} +
+ } + onChange={(val: string) => { + onChange(val); + const person = uninvitedPeople?.find((p) => p.member.id === val); - - - {uninvitedPeople?.length === 0 ? ( -
- Invite to workspace to add members -
- ) : ( - uninvitedPeople?.map((person) => ( - - `${active ? "bg-indigo-50" : ""} ${ - selected ? "bg-indigo-50 font-medium" : "" - } cursor-default select-none p-2 text-gray-900` - } - value={{ - id: person.member.id, - email: person.member.email, - }} - > - {person.member.email} - - )) - )} -
-
-
-

- {errors.user_id && errors.user_id.message} -

- - )} -
+ setValue("member_id", val); + setValue("email", person?.member.email ?? ""); + }} + input + width="w-full" + > + {uninvitedPeople?.map((person) => ( + + {person.member.email} + + ))} + )} />
@@ -236,6 +194,7 @@ const SendProjectInvitationModal: React.FC = ({ isOpen, setIsOpen, member } input + width="w-full" > {Object.entries(ROLE).map(([key, label]) => ( diff --git a/apps/app/components/ui/avatar.tsx b/apps/app/components/ui/avatar.tsx index 2b1c7b2cc..93ef49252 100644 --- a/apps/app/components/ui/avatar.tsx +++ b/apps/app/components/ui/avatar.tsx @@ -34,7 +34,7 @@ export const Avatar: React.FC = ({ user, index }) => ( />
) : ( -
+
{user?.first_name && user.first_name !== "" ? user.first_name.charAt(0) : user?.email?.charAt(0)} diff --git a/apps/app/components/ui/context-menu.tsx b/apps/app/components/ui/context-menu.tsx index 70d1e1265..acef49779 100644 --- a/apps/app/components/ui/context-menu.tsx +++ b/apps/app/components/ui/context-menu.tsx @@ -20,20 +20,12 @@ const ContextMenu = ({ position, children, title, isOpen, setIsOpen }: Props) => }; window.addEventListener("click", hideContextMenu); + window.addEventListener("keydown", (e: KeyboardEvent) => { + if (e.key === "Escape") hideContextMenu(); + }); return () => { window.removeEventListener("click", hideContextMenu); - }; - }, [isOpen, setIsOpen]); - - useEffect(() => { - const hideContextMenu = (e: KeyboardEvent) => { - if (e.key === "Escape" && isOpen) setIsOpen(false); - }; - - window.addEventListener("keydown", hideContextMenu); - - return () => { window.removeEventListener("keydown", hideContextMenu); }; }, [isOpen, setIsOpen]); diff --git a/apps/app/components/ui/custom-search-select.tsx b/apps/app/components/ui/custom-search-select.tsx index 7356aa50d..a90ca973a 100644 --- a/apps/app/components/ui/custom-search-select.tsx +++ b/apps/app/components/ui/custom-search-select.tsx @@ -16,7 +16,6 @@ type CustomSearchSelectProps = { label?: string | JSX.Element; textAlignment?: "left" | "center" | "right"; position?: "right" | "left"; - input?: boolean; noChevron?: boolean; customButton?: JSX.Element; optionsClassName?: string; @@ -33,7 +32,6 @@ export const CustomSearchSelect = ({ onChange, options, position = "left", - input = false, noChevron = false, customButton, optionsClassName = "", @@ -69,9 +67,7 @@ export const CustomSearchSelect = ({
@@ -142,10 +136,10 @@ export const CustomSearchSelect = ({ )) ) : ( -

No matching results

+

No matching results

) ) : ( -

Loading...

+

Loading...

)}
{footerOption} @@ -170,9 +164,7 @@ export const CustomSearchSelect = ({
setQuery(e.target.value)} placeholder="Type to search..." displayValue={(assigned: any) => assigned?.name} />
-
+
{filteredOptions ? ( filteredOptions.length > 0 ? ( filteredOptions.map((option) => ( @@ -235,10 +225,10 @@ export const CustomSearchSelect = ({ )) ) : ( -

No matching results

+

No matching results

) ) : ( -

Loading...

+

Loading...

)}
{footerOption} diff --git a/apps/app/components/ui/datepicker.tsx b/apps/app/components/ui/datepicker.tsx index 069543189..1e30ad97f 100644 --- a/apps/app/components/ui/datepicker.tsx +++ b/apps/app/components/ui/datepicker.tsx @@ -36,15 +36,15 @@ export const CustomDatePicker: React.FC = ({ }} className={`${className} ${ renderAs === "input" - ? "block bg-transparent text-sm focus:outline-none border-gray-300 px-3 py-2" + ? "block border-gray-300 bg-transparent px-3 py-2 text-sm focus:outline-none" : renderAs === "button" - ? `px-2 py-1 text-xs shadow-sm ${ + ? `px-3 py-1.5 text-xs shadow-sm ${ disabled ? "" : "hover:bg-gray-100" - } focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 duration-300` + } duration-300 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500` : "" } ${error ? "border-red-500 bg-red-100" : ""} ${ disabled ? "cursor-not-allowed" : "cursor-pointer" - } w-full rounded-md bg-transparent border caret-transparent`} + } w-full rounded-md border bg-transparent caret-transparent`} dateFormat="dd-MM-yyyy" isClearable={isClearable} disabled={disabled}