fix: issue relation mutation and draft issue (#2340)
* fix: issue relation mutation and draft issue * fix: 'New Issue' in gantt view fix: emoji select going under * fix: profile page typo
This commit is contained in:
parent
d9bd07886f
commit
cecdf890de
13 changed files with 268 additions and 184 deletions
|
|
@ -6,6 +6,7 @@ import { useRouter } from "next/router";
|
|||
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
||||
import { Draggable } from "react-beautiful-dnd";
|
||||
// components
|
||||
import { CreateUpdateDraftIssueModal } from "components/issues";
|
||||
import { BoardHeader, SingleBoardIssue, BoardInlineCreateIssueForm } from "components/core";
|
||||
// ui
|
||||
import { CustomMenu } from "components/ui";
|
||||
|
|
@ -57,6 +58,7 @@ export const SingleBoard: React.FC<Props> = (props) => {
|
|||
const [isCollapsed, setIsCollapsed] = useState(true);
|
||||
|
||||
const [isInlineCreateIssueFormOpen, setIsInlineCreateIssueFormOpen] = useState(false);
|
||||
const [isCreateDraftIssueModalOpen, setIsCreateDraftIssueModalOpen] = useState(false);
|
||||
|
||||
const { displayFilters, groupedIssues } = viewProps;
|
||||
|
||||
|
|
@ -96,10 +98,27 @@ export const SingleBoard: React.FC<Props> = (props) => {
|
|||
scrollToBottom();
|
||||
};
|
||||
|
||||
const handleAddIssueToGroup = () => {
|
||||
if (isDraftIssuesPage) setIsCreateDraftIssueModalOpen(true);
|
||||
else if (isMyIssuesPage || isProfileIssuesPage) addIssueToGroup();
|
||||
else onCreateClick();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`flex-shrink-0 ${!isCollapsed ? "" : "flex h-full flex-col w-96"}`}>
|
||||
<CreateUpdateDraftIssueModal
|
||||
isOpen={isCreateDraftIssueModalOpen}
|
||||
handleClose={() => setIsCreateDraftIssueModalOpen(false)}
|
||||
prePopulateData={{
|
||||
...(cycleId && { cycle: cycleId.toString() }),
|
||||
...(moduleId && { module: moduleId.toString() }),
|
||||
[displayFilters?.group_by! === "labels" ? "labels_list" : displayFilters?.group_by!]:
|
||||
displayFilters?.group_by === "labels" ? [groupTitle] : groupTitle,
|
||||
}}
|
||||
/>
|
||||
|
||||
<BoardHeader
|
||||
addIssueToGroup={addIssueToGroup}
|
||||
addIssueToGroup={handleAddIssueToGroup}
|
||||
currentState={currentState}
|
||||
groupTitle={groupTitle}
|
||||
isCollapsed={isCollapsed}
|
||||
|
|
@ -218,21 +237,22 @@ export const SingleBoard: React.FC<Props> = (props) => {
|
|||
{displayFilters?.group_by !== "created_by" && (
|
||||
<div>
|
||||
{type === "issue"
|
||||
? !disableAddIssueOption && (
|
||||
? !disableAddIssueOption &&
|
||||
!isDraftIssuesPage && (
|
||||
<button
|
||||
type="button"
|
||||
className="flex items-center gap-2 font-medium text-custom-primary outline-none p-1"
|
||||
onClick={() => {
|
||||
if (isDraftIssuesPage || isMyIssuesPage || isProfileIssuesPage) {
|
||||
addIssueToGroup();
|
||||
} else onCreateClick();
|
||||
if (isMyIssuesPage || isProfileIssuesPage) addIssueToGroup();
|
||||
else onCreateClick();
|
||||
}}
|
||||
>
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
Add Issue
|
||||
</button>
|
||||
)
|
||||
: !disableUserActions && (
|
||||
: !disableUserActions &&
|
||||
!isDraftIssuesPage && (
|
||||
<CustomMenu
|
||||
customButton={
|
||||
<button
|
||||
|
|
@ -246,7 +266,13 @@ export const SingleBoard: React.FC<Props> = (props) => {
|
|||
position="left"
|
||||
noBorder
|
||||
>
|
||||
<CustomMenu.MenuItem onClick={() => onCreateClick()}>
|
||||
<CustomMenu.MenuItem
|
||||
onClick={() => {
|
||||
if (isDraftIssuesPage) setIsCreateDraftIssueModalOpen(true);
|
||||
else if (isMyIssuesPage || isProfileIssuesPage) addIssueToGroup();
|
||||
else onCreateClick();
|
||||
}}
|
||||
>
|
||||
Create new
|
||||
</CustomMenu.MenuItem>
|
||||
{openIssuesListModal && (
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import projectService from "services/project.service";
|
|||
// hooks
|
||||
import useProjects from "hooks/use-projects";
|
||||
// components
|
||||
import { CreateUpdateDraftIssueModal } from "components/issues";
|
||||
import { SingleListIssue, ListInlineCreateIssueForm } from "components/core";
|
||||
// ui
|
||||
import { Avatar, CustomMenu } from "components/ui";
|
||||
|
|
@ -75,6 +76,7 @@ export const SingleList: React.FC<Props> = (props) => {
|
|||
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
|
||||
|
||||
const [isCreateIssueFormOpen, setIsCreateIssueFormOpen] = useState(false);
|
||||
const [isDraftIssuesModalOpen, setIsDraftIssuesModalOpen] = useState(false);
|
||||
|
||||
const isMyIssuesPage = router.pathname.split("/")[3] === "my-issues";
|
||||
const isProfileIssuesPage = router.pathname.split("/")[2] === "profile";
|
||||
|
|
@ -208,154 +210,169 @@ export const SingleList: React.FC<Props> = (props) => {
|
|||
if (!groupedIssues) return null;
|
||||
|
||||
return (
|
||||
<Disclosure as="div" defaultOpen>
|
||||
{({ open }) => (
|
||||
<div>
|
||||
<div className="flex items-center justify-between px-4 py-2.5 bg-custom-background-90">
|
||||
<Disclosure.Button>
|
||||
<div className="flex items-center gap-x-3">
|
||||
{displayFilters?.group_by !== null && (
|
||||
<div className="flex items-center">{getGroupIcon()}</div>
|
||||
)}
|
||||
{displayFilters?.group_by !== null ? (
|
||||
<h2
|
||||
className={`text-sm font-semibold leading-6 text-custom-text-100 ${
|
||||
displayFilters?.group_by === "created_by" ? "" : "capitalize"
|
||||
}`}
|
||||
>
|
||||
{getGroupTitle()}
|
||||
</h2>
|
||||
) : (
|
||||
<h2 className="font-medium leading-5">All Issues</h2>
|
||||
)}
|
||||
<span className="text-custom-text-200 min-w-[2.5rem] rounded-full bg-custom-background-80 py-1 text-center text-xs">
|
||||
{groupedIssues[groupTitle as keyof IIssue].length}
|
||||
</span>
|
||||
</div>
|
||||
</Disclosure.Button>
|
||||
{isArchivedIssues ? (
|
||||
""
|
||||
) : type === "issue" ? (
|
||||
!disableAddIssueOption && (
|
||||
<button
|
||||
type="button"
|
||||
className="p-1 text-custom-text-200 hover:bg-custom-background-80"
|
||||
onClick={() => {
|
||||
if (isDraftIssuesPage || isMyIssuesPage || isProfileIssuesPage) {
|
||||
addIssueToGroup();
|
||||
} else setIsCreateIssueFormOpen(true);
|
||||
}}
|
||||
>
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
</button>
|
||||
)
|
||||
) : disableUserActions ? (
|
||||
""
|
||||
) : (
|
||||
<CustomMenu
|
||||
customButton={
|
||||
<div className="flex cursor-pointer items-center">
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
</div>
|
||||
}
|
||||
position="right"
|
||||
noBorder
|
||||
>
|
||||
<CustomMenu.MenuItem onClick={() => setIsCreateIssueFormOpen(true)}>
|
||||
Create new
|
||||
</CustomMenu.MenuItem>
|
||||
{openIssuesListModal && (
|
||||
<CustomMenu.MenuItem onClick={openIssuesListModal}>
|
||||
Add an existing issue
|
||||
</CustomMenu.MenuItem>
|
||||
)}
|
||||
</CustomMenu>
|
||||
)}
|
||||
</div>
|
||||
<Transition
|
||||
show={open}
|
||||
enter="transition duration-100 ease-out"
|
||||
enterFrom="transform opacity-0"
|
||||
enterTo="transform opacity-100"
|
||||
leave="transition duration-75 ease-out"
|
||||
leaveFrom="transform opacity-100"
|
||||
leaveTo="transform opacity-0"
|
||||
>
|
||||
<Disclosure.Panel>
|
||||
{groupedIssues[groupTitle] ? (
|
||||
groupedIssues[groupTitle].length > 0 ? (
|
||||
groupedIssues[groupTitle].map((issue, index) => (
|
||||
<SingleListIssue
|
||||
key={issue.id}
|
||||
type={type}
|
||||
issue={issue}
|
||||
projectId={issue.project_detail.id}
|
||||
groupTitle={groupTitle}
|
||||
index={index}
|
||||
editIssue={() => handleIssueAction(issue, "edit")}
|
||||
makeIssueCopy={() => handleIssueAction(issue, "copy")}
|
||||
handleDeleteIssue={() => handleIssueAction(issue, "delete")}
|
||||
handleDraftIssueSelect={
|
||||
handleDraftIssueAction
|
||||
? () => handleDraftIssueAction(issue, "edit")
|
||||
: undefined
|
||||
}
|
||||
handleDraftIssueDelete={
|
||||
handleDraftIssueAction
|
||||
? () => handleDraftIssueAction(issue, "delete")
|
||||
: undefined
|
||||
}
|
||||
handleMyIssueOpen={handleMyIssueOpen}
|
||||
removeIssue={() => {
|
||||
if (removeIssue !== null && issue.bridge_id)
|
||||
removeIssue(issue.bridge_id, issue.id);
|
||||
}}
|
||||
disableUserActions={disableUserActions}
|
||||
user={user}
|
||||
userAuth={userAuth}
|
||||
viewProps={viewProps}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<p className="bg-custom-background-100 px-4 py-2.5 text-sm text-custom-text-200">
|
||||
No issues.
|
||||
</p>
|
||||
)
|
||||
) : (
|
||||
<div className="flex h-full w-full items-center justify-center">Loading...</div>
|
||||
)}
|
||||
<>
|
||||
<CreateUpdateDraftIssueModal
|
||||
isOpen={isDraftIssuesModalOpen}
|
||||
handleClose={() => setIsDraftIssuesModalOpen(false)}
|
||||
prePopulateData={{
|
||||
...(cycleId && { cycle: cycleId.toString() }),
|
||||
...(moduleId && { module: moduleId.toString() }),
|
||||
[displayFilters?.group_by! === "labels" ? "labels_list" : displayFilters?.group_by!]:
|
||||
displayFilters?.group_by === "labels" ? [groupTitle] : groupTitle,
|
||||
}}
|
||||
/>
|
||||
|
||||
<ListInlineCreateIssueForm
|
||||
isOpen={isCreateIssueFormOpen && !disableAddIssueOption}
|
||||
handleClose={() => setIsCreateIssueFormOpen(false)}
|
||||
prePopulatedData={{
|
||||
...(cycleId && { cycle: cycleId.toString() }),
|
||||
...(moduleId && { module: moduleId.toString() }),
|
||||
[displayFilters?.group_by!]: groupTitle,
|
||||
}}
|
||||
/>
|
||||
|
||||
{!disableAddIssueOption && !isCreateIssueFormOpen && (
|
||||
// TODO: add border here
|
||||
<div className="w-full bg-custom-background-100 px-6 py-3 border-b border-custom-border-100">
|
||||
<Disclosure as="div" defaultOpen>
|
||||
{({ open }) => (
|
||||
<div>
|
||||
<div className="flex items-center justify-between px-4 py-2.5 bg-custom-background-90">
|
||||
<Disclosure.Button>
|
||||
<div className="flex items-center gap-x-3">
|
||||
{displayFilters?.group_by !== null && (
|
||||
<div className="flex items-center">{getGroupIcon()}</div>
|
||||
)}
|
||||
{displayFilters?.group_by !== null ? (
|
||||
<h2
|
||||
className={`text-sm font-semibold leading-6 text-custom-text-100 ${
|
||||
displayFilters?.group_by === "created_by" ? "" : "capitalize"
|
||||
}`}
|
||||
>
|
||||
{getGroupTitle()}
|
||||
</h2>
|
||||
) : (
|
||||
<h2 className="font-medium leading-5">All Issues</h2>
|
||||
)}
|
||||
<span className="text-custom-text-200 min-w-[2.5rem] rounded-full bg-custom-background-80 py-1 text-center text-xs">
|
||||
{groupedIssues[groupTitle as keyof IIssue].length}
|
||||
</span>
|
||||
</div>
|
||||
</Disclosure.Button>
|
||||
{isArchivedIssues ? (
|
||||
""
|
||||
) : type === "issue" ? (
|
||||
!disableAddIssueOption && (
|
||||
<button
|
||||
type="button"
|
||||
className="p-1 text-custom-text-200 hover:bg-custom-background-80"
|
||||
onClick={() => {
|
||||
if (isDraftIssuesPage || isMyIssuesPage || isProfileIssuesPage) {
|
||||
addIssueToGroup();
|
||||
} else setIsCreateIssueFormOpen(true);
|
||||
if (isDraftIssuesPage) setIsDraftIssuesModalOpen(true);
|
||||
else if (isMyIssuesPage || isProfileIssuesPage) addIssueToGroup();
|
||||
else setIsCreateIssueFormOpen(true);
|
||||
}}
|
||||
className="flex items-center gap-x-[6px] text-custom-primary-100 px-2 py-1 rounded-md"
|
||||
>
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
<span className="text-sm font-medium text-custom-primary-100">New Issue</span>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
) : disableUserActions ? (
|
||||
""
|
||||
) : (
|
||||
<CustomMenu
|
||||
customButton={
|
||||
<div className="flex cursor-pointer items-center">
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
</div>
|
||||
}
|
||||
position="right"
|
||||
noBorder
|
||||
>
|
||||
<CustomMenu.MenuItem onClick={() => setIsCreateIssueFormOpen(true)}>
|
||||
Create new
|
||||
</CustomMenu.MenuItem>
|
||||
{openIssuesListModal && (
|
||||
<CustomMenu.MenuItem onClick={openIssuesListModal}>
|
||||
Add an existing issue
|
||||
</CustomMenu.MenuItem>
|
||||
)}
|
||||
</CustomMenu>
|
||||
)}
|
||||
</Disclosure.Panel>
|
||||
</Transition>
|
||||
</div>
|
||||
)}
|
||||
</Disclosure>
|
||||
</div>
|
||||
<Transition
|
||||
show={open}
|
||||
enter="transition duration-100 ease-out"
|
||||
enterFrom="transform opacity-0"
|
||||
enterTo="transform opacity-100"
|
||||
leave="transition duration-75 ease-out"
|
||||
leaveFrom="transform opacity-100"
|
||||
leaveTo="transform opacity-0"
|
||||
>
|
||||
<Disclosure.Panel>
|
||||
{groupedIssues[groupTitle] ? (
|
||||
groupedIssues[groupTitle].length > 0 ? (
|
||||
groupedIssues[groupTitle].map((issue, index) => (
|
||||
<SingleListIssue
|
||||
key={issue.id}
|
||||
type={type}
|
||||
issue={issue}
|
||||
projectId={issue.project_detail.id}
|
||||
groupTitle={groupTitle}
|
||||
index={index}
|
||||
editIssue={() => handleIssueAction(issue, "edit")}
|
||||
makeIssueCopy={() => handleIssueAction(issue, "copy")}
|
||||
handleDeleteIssue={() => handleIssueAction(issue, "delete")}
|
||||
handleDraftIssueSelect={
|
||||
handleDraftIssueAction
|
||||
? () => handleDraftIssueAction(issue, "edit")
|
||||
: undefined
|
||||
}
|
||||
handleDraftIssueDelete={
|
||||
handleDraftIssueAction
|
||||
? () => handleDraftIssueAction(issue, "delete")
|
||||
: undefined
|
||||
}
|
||||
handleMyIssueOpen={handleMyIssueOpen}
|
||||
removeIssue={() => {
|
||||
if (removeIssue !== null && issue.bridge_id)
|
||||
removeIssue(issue.bridge_id, issue.id);
|
||||
}}
|
||||
disableUserActions={disableUserActions}
|
||||
user={user}
|
||||
userAuth={userAuth}
|
||||
viewProps={viewProps}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<p className="bg-custom-background-100 px-4 py-2.5 text-sm text-custom-text-200">
|
||||
No issues.
|
||||
</p>
|
||||
)
|
||||
) : (
|
||||
<div className="flex h-full w-full items-center justify-center">Loading...</div>
|
||||
)}
|
||||
|
||||
<ListInlineCreateIssueForm
|
||||
isOpen={isCreateIssueFormOpen && !disableAddIssueOption}
|
||||
handleClose={() => setIsCreateIssueFormOpen(false)}
|
||||
prePopulatedData={{
|
||||
...(cycleId && { cycle: cycleId.toString() }),
|
||||
...(moduleId && { module: moduleId.toString() }),
|
||||
[displayFilters?.group_by! === "labels"
|
||||
? "labels_list"
|
||||
: displayFilters?.group_by!]:
|
||||
displayFilters?.group_by === "labels" ? [groupTitle] : groupTitle,
|
||||
}}
|
||||
/>
|
||||
|
||||
{!disableAddIssueOption && !isCreateIssueFormOpen && !isDraftIssuesPage && (
|
||||
<div className="w-full bg-custom-background-100 px-6 py-3 border-b border-custom-border-100">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
if (isDraftIssuesPage) setIsDraftIssuesModalOpen(true);
|
||||
else if (isMyIssuesPage || isProfileIssuesPage) addIssueToGroup();
|
||||
else setIsCreateIssueFormOpen(true);
|
||||
}}
|
||||
className="flex items-center gap-x-[6px] text-custom-primary-100 px-2 py-1 rounded-md"
|
||||
>
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
<span className="text-sm font-medium text-custom-primary-100">New Issue</span>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</Disclosure.Panel>
|
||||
</Transition>
|
||||
</div>
|
||||
)}
|
||||
</Disclosure>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue